🦀 Escrito em Rust • Rápido e Seguro

Parsing de NF-e simplificado

Biblioteca Rust de alto desempenho para parsing e serialização de Nota Fiscal Eletrônica brasileira. Suporte ao Layout 4.00 da SEFAZ.

Cargo.toml
[dependencies]
nfe = "0.1.0"

Funcionalidades

Tudo que você precisa para trabalhar com NF-e em Rust

Alto Desempenho

Parsing e serialização extremamente rápidos graças ao quick-xml e otimizações do Rust.

🔒

Type-Safe

Tipagem forte com enums para todos os campos codificados, prevenindo erros em tempo de compilação.

📋

Layout 4.00

Suporte completo ao layout 4.00 da NF-e conforme especificação da SEFAZ.

🔄

Serialização

Converta facilmente entre estruturas Rust e XML válido para transmissão à SEFAZ.

📦

Modelos Completos

Suporte a NF-e (modelo 55) e NFC-e (modelo 65) com todas as estruturas necessárias.

🧪

Bem Testado

Cobertura de testes abrangente para garantir a conformidade com o padrão da SEFAZ.

Fácil de Usar

Parse de XML de NF-e em poucas linhas de código. A biblioteca cuida de toda a complexidade do XML para você.

Acesse todos os campos da nota fiscal através de structs Rust bem tipadas e documentadas.

  • Parse de arquivos XML
  • Parse de strings XML
  • Serialização para XML
  • Validação automática de tipos
  • Tratamento de erros robusto
use nfe::Nfe;

fn main() -> Result<(), nfe::Error> {
    // Parse de string XML (sem namespace)
    let xml = std::fs::read_to_string("nota.xml")?;
    let xml = xml.replace(
        "xmlns=\"http://www.portalfiscal.inf.br/nfe\"", ""
    );

    // Extrair tag <NFe> e fazer parse
    let nfe: Nfe = xml.parse()?;

    // Acessar dados da nota
    println!("Chave: {}", nfe.chave_acesso);
    println!("Emitente: {:?}", nfe.emit.razao_social);
    println!("Total: R$ {:.2}", nfe.totais.valor_total);

    // Iterar sobre os itens
    for item in &nfe.itens {
        println!("{}. {} - R$ {:.2}",
            item.numero,
            item.produto.descricao,
            item.produto.valor_bruto
        );
    }

    Ok(())
}

Guia de Uso

Aprenda a utilizar a biblioteca passo a passo

1. Parsing de XML de NF-e
use nfe::Nfe;

// O XML da SEFAZ contém namespace que deve ser removido
let xml_original = std::fs::read_to_string("nfe.xml")?;
let xml = xml_original.replace(
    "xmlns=\"http://www.portalfiscal.inf.br/nfe\"", ""
);

// Se o XML for nfeProc (com protocolo), extraia apenas a tag <NFe>
let nfe_start = xml.find("<NFe").unwrap();
let nfe_end = xml.find("</NFe>").unwrap() + 6;
let nfe_xml = &xml[nfe_start..nfe_end];

// Parse usando o trait FromStr
let nfe: Nfe = nfe_xml.parse()?;
2. Acessando Dados do Emitente
// Dados do emitente (quem emitiu a nota)
if let Some(cnpj) = &nfe.emit.cnpj {
    println!("CNPJ: {}", cnpj);
}
if let Some(razao) = &nfe.emit.razao_social {
    println!("Razão Social: {}", razao);
}

// Endereço do emitente
println!("Endereço: {}, {}",
    nfe.emit.endereco.logradouro,
    nfe.emit.endereco.numero
);
println!("Cidade: {} - {}",
    nfe.emit.endereco.nome_municipio,
    nfe.emit.endereco.sigla_uf
);
3. Iterando sobre Itens/Produtos
// Cada item contém produto, impostos e número sequencial
for item in &nfe.itens {
    let prod = &item.produto;

    println!("Item {}: {}", item.numero, prod.descricao);
    println!("  Código: {}", prod.codigo);
    println!("  NCM: {}", prod.ncm);
    println!("  Qtd: {} {} x R$ {:.2} = R$ {:.2}",
        prod.quantidade,
        prod.unidade,
        prod.valor_unitario,
        prod.valor_bruto
    );

    // CFOP está na tributação do produto
    println!("  CFOP: {}", prod.tributacao.cfop);

    // Verificar desconto
    if let Some(desc) = prod.valor_desconto {
        println!("  Desconto: R$ {:.2}", desc);
    }
}
4. Totais e Impostos
// Totais da nota fiscal
println!("Valor Produtos: R$ {:.2}", nfe.totais.valor_produtos);
println!("Valor Frete: R$ {:.2}", nfe.totais.valor_frete);
println!("Valor Desconto: R$ {:.2}", nfe.totais.valor_desconto);
println!("Valor Total: R$ {:.2}", nfe.totais.valor_total);
println!("Tributos Aprox.: R$ {:.2}", nfe.totais.valor_aproximado_tributos);

// Totais de ICMS
println!("Base ICMS: R$ {:.2}", nfe.totais.base_calculo_icms);
println!("Valor ICMS: R$ {:.2}", nfe.totais.valor_icms);
5. Identificação da Nota
use nfe::{TipoAmbiente, ModeloDocumentoFiscal, TipoOperacao};

// Dados de identificação (ide)
println!("Chave de Acesso: {}", nfe.chave_acesso);
println!("Número: {}", nfe.ide.numero);
println!("Série: {}", nfe.ide.serie);
println!("Natureza: {}", nfe.ide.operacao.natureza);

// Verificar ambiente (produção ou homologação)
match nfe.ide.ambiente {
    TipoAmbiente::Producao => println!("Ambiente: Produção"),
    TipoAmbiente::Homologacao => println!("Ambiente: Homologação"),
}

// Verificar tipo de operação
match nfe.ide.operacao.tipo {
    TipoOperacao::Entrada => println!("Operação: Entrada"),
    TipoOperacao::Saida => println!("Operação: Saída"),
}
6. Tratamento de Erros
use nfe::{Nfe, Error};

fn processar_nfe(xml: &str) -> Result<Nfe, Error> {
    let nfe: Nfe = xml.parse()?;
    Ok(nfe)
}

fn main() {
    match processar_nfe(xml_content) {
        Ok(nfe) => {
            println!("NF-e processada: {}", nfe.chave_acesso);
        }
        Err(Error::Xml(e)) => {
            eprintln!("Erro de XML: {}", e);
        }
        Err(Error::Io(e)) => {
            eprintln!("Erro de IO: {}", e);
        }
        Err(e) => {
            eprintln!("Erro: {}", e);
        }
    }
}

Estruturas Disponíveis

Todas as estruturas da NF-e mapeadas para Rust

Nfe
Estrutura principal da Nota Fiscal Eletrônica
Identificacao
Dados de identificação da NF-e (ide)
Emitente
Dados do emitente da nota (emit)
Destinatario
Dados do destinatário (dest)
Item
Itens/produtos da nota (det)
Produto
Dados do produto (prod)
Imposto
Impostos do item (ICMS, PIS, COFINS)
Totalizacao
Totais da nota fiscal (total)
Transporte
Dados de transporte (transp)
Endereco
Endereços (emitente/destinatário)