Skip to content

Como usar

Petrus Silva Costa edited this page May 30, 2026 · 10 revisions

Como usar (13 linguagens)

Versão canônica no repo: docs/USAGE.md. Esta página resume; o documento no repo traz os passos completos, as receitas e as pegadinhas detalhadas. Em caso de dúvida, ele é a fonte única de verdade.

Esta página mostra, de forma enxuta, como obter a lib e calcular um hash em cada uma das 13 linguagens. Cada port é autossuficiente e tem o seu próprio README com a API completa.

Não sabe o que é tudo isto? Comece por Conceitos (sem código) ou pelo Tutorial (mão na massa). Dúvidas e erros: FAQ.

Antes de tudo

As 13 linguagens produzem o mesmo hash, byte a byte, para o mesmo XML de entrada. 9 registries canonicos no ar: Python (PyPI, pip install tiss-hash), Node.js (npm, npm install tiss-hash), Rust (crates.io, cargo add tiss-hash), PHP (Packagist, composer require petrinhu/tiss-hash), C# (NuGet, dotnet add package TissHash), Go (go get ...@v0.2.1), Dart (pub.dev, dart pub add tiss_hash), Java (Maven Central, io.github.petrinhu:tiss-hash:0.1.0) e Kotlin (Maven Central, io.github.petrinhu:tiss-hash-kotlin:0.1.0). WASM (npm) e opcional e em preparacao. C, C++ e Delphi/FPC nao tem registry canonico (instalar do checkout ou releases).

Primeiro, baixe o repositório:

git clone https://github.com/petrinhu/TISS_ANS_hash.git
cd TISS_ANS_hash

Todos os exemplos usam o XML sintético conformance/inputs/syn_minimal.xml, cujo hash ilustrativo é 3aa0c578c95cdb861a125f480a8a4de5. Para XMLs reais o hash será outro.

Linguagem Pacote / módulo Diretório do port
Python tiss-hash langs/python/
Rust crate tiss-hash langs/rust/
C tiss_hash (lib + header) langs/c/
C++ tiss_hash (header-only) langs/cpp/
Node.js tiss-hash langs/node/
PHP petrinhu/tiss-hash langs/php/
Java tiss-hash (jar) langs/java/
Go módulo tisshash langs/go/
C# TissHash (.NET) langs/csharp/
Kotlin tiss-hash-kotlin (jar) langs/kotlin/
Delphi / Object Pascal unit TissHash (FPC) langs/delphi/
Dart pacote tiss_hash langs/dart/
WASM tiss-hash-wasm (pkg) langs/wasm/

Python

Toolchain: Python 3.10+. Obter (publicado no PyPI): pip install tiss-hash. Do fonte (alternativa): cd langs/python && pip install -e .. Única dependência: defusedxml.

from tiss_hash import hash_tiss, hash_tiss_file

with open("conformance/inputs/syn_minimal.xml", "rb") as f:  # rb = bytes
    print(hash_tiss(f.read()))

print(hash_tiss_file("conformance/inputs/syn_minimal.xml"))

Erro de XML malformado: exceção InvalidTissXml. Detalhe: USAGE seção 2.

Rust

Toolchain: Rust estável (rustup). Obter (publicado no crates.io): dentro do seu projeto Rust, cargo add tiss-hash (ou tiss-hash = "0.1" em [dependencies] do Cargo.toml). Do fonte (alternativa): cd langs/rust && cargo build.

use tiss_hash::{hash_tiss, hash_tiss_file, TissHashError};

fn main() -> Result<(), TissHashError> {
    let raw = std::fs::read("../../conformance/inputs/syn_minimal.xml")?;
    println!("{}", hash_tiss(&raw)?);
    println!("{}", hash_tiss_file("../../conformance/inputs/syn_minimal.xml")?);
    Ok(())
}

Erro: enum TissHashError com InvalidXml(String) e Io(std::io::Error). Detalhe: USAGE seção 3.

C

Toolchain: compilador C (gcc/clang), CMake, libxml2 e OpenSSL. Instalar dependências (exemplos): Fedora sudo dnf install libxml2-devel openssl-devel cmake gcc; Debian/Ubuntu sudo apt install libxml2-dev libssl-dev cmake gcc. Build:

cd langs/c
cmake -B build -S .
cmake --build build -j

C não tem registry central; após cmake --install build, outros projetos a localizam via pkg-config --cflags --libs tiss-hash ou find_package(tiss_hash). Snippet, compilação e tratamento de erro completos: USAGE seção 4.

C++

Toolchain: compilador C++20 (g++/clang++), CMake, pugixml (baixado automaticamente se faltar) e OpenSSL. Build:

cd langs/cpp
cmake -B build -S .
cmake --build build -j

Após cmake --install build, projetos a localizam via find_package(tiss_hash_cpp). Snippet e erro completos: USAGE seção 5.

Node.js

Toolchain: Node.js LTS. Obter (publicado no npm): npm install tiss-hash. Do fonte (alternativa): cd langs/node && npm install. Única dependência: @xmldom/xmldom.

import { hashTiss, hashTissFile } from 'tiss-hash';
import { readFileSync } from 'node:fs';

console.log(hashTiss(readFileSync('../../conformance/inputs/syn_minimal.xml')));     // síncrono
console.log(await hashTissFile('../../conformance/inputs/syn_minimal.xml'));         // assíncrono

Salve como .mjs (ativa módulos ESM) e rode com node exemplo.mjs. Detalhe: USAGE seção 6.

PHP

Toolchain: PHP 8.x + Composer. Obter (publicado no Packagist): composer require petrinhu/tiss-hash. O Packagist serve o pacote a partir de um repositório dedicado (github.com/petrinhu/tiss-hash-php, espelho somente-leitura de langs/php); para você é transparente. Do fonte (alternativa): composer require petrinhu/tiss-hash:@dev apontando para o checkout. Snippet, saída e tratamento de erro: USAGE seção 7.

Java

Toolchain: JDK 17+ e Maven/Gradle. Obter (publicado no Maven Central):

<dependency>
  <groupId>io.github.petrinhu</groupId>
  <artifactId>tiss-hash</artifactId>
  <version>0.1.0</version>
</dependency>

Gradle: implementation("io.github.petrinhu:tiss-hash:0.1.0"). Do fonte (alternativa): mvn package no checkout. Snippet e tratamento de erro (InvalidTissXmlException): USAGE secao 8.

Go

Toolchain: Go recente. Obter (publicado pela tag de versão):

go get github.com/petrinhu/TISS_ANS_hash/langs/go@v0.2.1
package main

import (
    "fmt"
    "os"
    tisshash "github.com/petrinhu/TISS_ANS_hash/langs/go"
)

func main() {
    data, _ := os.ReadFile("../../conformance/inputs/syn_minimal.xml")
    hash, _ := tisshash.HashTiss(data)
    fmt.Println(hash)

    hashFile, _ := tisshash.HashTissFile("../../conformance/inputs/syn_minimal.xml")
    fmt.Println(hashFile)
}

Em código real, trate o error retornado em vez de ignorar com _. Detalhe: USAGE seção 9.

C# / .NET

Toolchain: .NET SDK. Obter (publicado no NuGet): dentro do seu projeto (pasta com .csproj), dotnet add package TissHash. Do fonte (alternativa): dotnet add reference .../langs/csharp/src/TissHash/TissHash.csproj. Snippet e tratamento de erro: USAGE seção 10.

Kotlin

Toolchain: JDK 17+ e o compilador Kotlin. Obter (publicado no Maven Central):

// build.gradle.kts
dependencies {
    implementation("io.github.petrinhu:tiss-hash-kotlin:0.1.0")
}

Maven: <groupId>io.github.petrinhu</groupId> <artifactId>tiss-hash-kotlin</artifactId> <version>0.1.0</version>. Do fonte (alternativa): ./build.sh jar no checkout.

import io.github.petrinhu.tisshash.hashTiss
import io.github.petrinhu.tisshash.hashTissFile
import java.nio.file.Files
import java.nio.file.Path

fun main() {
    val xml = Files.readAllBytes(Path.of("conformance/inputs/syn_minimal.xml"))
    println(hashTiss(xml))   // 3aa0c578c95cdb861a125f480a8a4de5
    println(hashTissFile(Path.of("conformance/inputs/syn_minimal.xml")))
}

Zero dependência de runtime além do kotlin-stdlib (parser XML e MD5 vêm da JDK). Erro: exceção InvalidTissXmlException. Interop a partir de Java: io.github.petrinhu.tisshash.TissHash.hashTiss(...). Detalhe: USAGE seção 11.

Delphi / Object Pascal (Free Pascal)

Toolchain: Free Pascal (FPC) 3.2+ (Fedora sudo dnf install fpc; Debian/Ubuntu sudo apt install fpc; Windows/macOS pelo site oficial ou pelo Lazarus). Compila também no Delphi ({$mode delphi}). As units usadas (fcl-xml, md5, fcl-json) já vêm na instalação padrão; nada extra para baixar. Não há registry: a "obtenção" é compilar o fonte.

cd langs/delphi
make            # compila a lib + CLI + testes em build/
make test       # roda os 20 vetores de conformidade
program exemplo;
{$mode delphi}{$H+}
uses SysUtils, TissHash;
begin
  Writeln(HashTissFile('conformance/inputs/syn_minimal.xml'));  // 3aa0c578c95cdb861a125f480a8a4de5
end.

Compile apontando o search path de units: fpc -O2 -Mdelphi -Fulangs/delphi/src exemplo.pas. Erro: exceção EInvalidTissXml. Para reusar, coloque a unit TissHash (src/TissHash.pas) no search path do seu projeto. Detalhe: USAGE seção 12.

Dart

Toolchain: Dart 3.4+ (também vem com o SDK do Flutter). Obter (publicado no pub.dev): dart pub add tiss_hash (em Flutter, flutter pub add tiss_hash). Do fonte (alternativa): cd langs/dart && dart pub get. Dependências: xml (parser) e crypto (MD5).

import 'dart:io';
import 'package:tiss_hash/tiss_hash.dart';

Future<void> main() async {
  final md5 = hashTiss(File('../../conformance/inputs/syn_minimal.xml').readAsBytesSync());
  print(md5);   // 3aa0c578c95cdb861a125f480a8a4de5
  print(await hashTissFile('../../conformance/inputs/syn_minimal.xml'));   // assíncrono
}

Salve em langs/dart e rode com dart run exemplo.dart. Erro: exceção InvalidTissXmlException. Detalhe: USAGE seção 13.

WASM (WebAssembly)

O port WASM calcula o hash no navegador do usuário (ou no Node), sem enviar nada para servidor nenhum. Esse é o argumento de privacidade mais forte do projeto: o XML TISS carrega PII (LGPD), e hashear no cliente faz com que o arquivo nunca saia da máquina. O core é o mesmo Rust compilado para wasm32-unknown-unknown, então o hash sai byte a byte idêntico aos outros 12 ports.

Para consumir o módulo já gerado (pkg/) basta um navegador moderno ou Node.js 20+. Para gerar o pkg/ a partir do fonte:

cd langs/wasm
bash build.sh      # compila + wasm-bindgen (gera pkg/web e pkg/node)

(quando publicado no npm: npm install tiss-hash-wasm)

No navegador (ESM; sirva por HTTP, não abra com file://):

<script type="module">
  import init, { hashTiss } from './pkg/web/tiss_hash_wasm.js';
  await init();   // carrega o .wasm uma vez
  const bytes = new Uint8Array(await file.arrayBuffer());
  console.log(hashTiss(bytes));   // 3aa0c578c95cdb861a125f480a8a4de5
</script>

No Node.js (binding pkg/node, CommonJS, sem init()):

import { createRequire } from 'node:module';
import { readFileSync } from 'node:fs';
const require = createRequire(import.meta.url);
const { hashTiss } = require('./pkg/node/tiss_hash_wasm.js');
console.log(hashTiss(new Uint8Array(readFileSync('../../conformance/inputs/syn_minimal.xml'))));   // 3aa0c578c95cdb861a125f480a8a4de5

Erro: hashTiss lança um Error (mensagem vem do core Rust, sem PII). Tipos TypeScript (.d.ts) gerados automaticamente. Detalhe: USAGE seção 14.

Pegadinhas (valem para os 13 ports)

  • Passe os bytes brutos. Leia o arquivo em modo binário; não decodifique nem reencode você mesmo. A lib controla o encoding internamente (UTF-8 para o MD5).
  • Não "arrume" o XML antes (formatadores, xmllint --format, --c14n, pretty-print mudam espaços e quebram o hash).
  • Não confie no hash já gravado dentro do <ans:hash>: recalcule sempre.
  • Não há diferença de resultado entre linguagens. Se o seu hash não bate, suspeite primeiro do encoding ou de normalização do XML, nunca da linguagem.

A lista completa com exemplos de "errado vs certo" está na seção 12 do USAGE. Para resolver erros específicos, veja o troubleshooting no FAQ.

Validar a lib na sua máquina

Cada port tem um comando de teste próprio (a tabela completa está na seção 13 do USAGE). A referência Python sobre um vetor sintético deve devolver o hash esperado:

python3 conformance/reference.py conformance/inputs/syn_minimal.xml
# 3aa0c578c95cdb861a125f480a8a4de5

Ver também

  • Tutorial: primeiro hash, passo a passo (em Python).
  • Conceitos: o porquê do projeto e o detalhe do encoding.
  • FAQ: glossário e solução de erros.
  • SPEC: a regra exata do algoritmo, com casos de borda.

Clone this wiki locally