-
-
Notifications
You must be signed in to change notification settings - Fork 0
Como usar
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.
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_hashTodos 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/ |
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.
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.
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 -jC 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.
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 -jApós cmake --install build, projetos a localizam via find_package(tiss_hash_cpp). Snippet e erro completos: USAGE seção 5.
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íncronoSalve como .mjs (ativa módulos ESM) e rode com node exemplo.mjs. Detalhe: USAGE seção 6.
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.
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.
Toolchain: Go recente. Obter (publicado pela tag de versão):
go get github.com/petrinhu/TISS_ANS_hash/langs/go@v0.2.1package 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.
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.
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.
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 conformidadeprogram 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.
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.
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')))); // 3aa0c578c95cdb861a125f480a8a4de5Erro: hashTiss lança um Error (mensagem vem do core Rust, sem PII). Tipos TypeScript (.d.ts) gerados automaticamente. Detalhe: USAGE seção 14.
- 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.
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
# 3aa0c578c95cdb861a125f480a8a4de5Repositório · Release v0.2.1 · Licença MIT · Esta wiki é a porta de entrada; o detalhe técnico mora no repo.