swhid

Crates.ioswhid
lib.rsswhid
version0.2.2
created_at2026-01-05 15:33:15.577671+00
updated_at2026-01-21 14:16:53.914488+00
descriptionSWHID v1.2 reference implementation - Complete SWHID (ISO/IEC 18670:2025) parsing and hashing with VCS integration
homepage
repositoryhttps://github.com/swhid/swhid-rs
max_upload_size
id2024060
size230,289
Val Lorentz (progval)

documentation

README

swhid-rs: SWHID v1.2 reference implementation

This crate provides a minimal implementation of the SWHID (SoftWare Hash IDentifier) format as defined in ISO/IEC 18670:2025 and detailed in the SWHID v1.2 specification;

This implementation is fully compliant with SWHID v1.2 and provides:

  • Core identifier representation and parsing/printing (swh:1:<tag>:<id>)
  • All SWHID v1.2 object types: contents (cnt), directories (dir), revisions (rev), releases (rel), snapshots (snp)
  • Qualified identifiers (origin, visit, anchor, path, lines, bytes)
  • SWHID v1.2 compliant hash computation for content and directory objects

VCS Integration (optional):

  • Computing rev, rel, snp SWHIDs from VCS metadata (requires git feature)
  • Git repository support for revision, release, and snapshot SWHID computation

Features

Feature Description
serde Enable Serialize/Deserialize for all public types
git Enable VCS integration for SWHID v1.2 revision/release/snapshot computation

Examples

Parsing a SWHID

use std::path::Path;
use swhid::*;

let swhid: Swhid = "swh:1:cnt:e69de29bb2d1d6434b8b29ae775ad8c2e48c5391".parse()?;
println!("Object type: {:?}", swhid.object_type()); // Content
println!("Digest: {}", swhid.digest_hex());

# Ok::<_, Box<dyn std::error::Error>>(())

Creating a SWHID

use std::path::Path;
use swhid::*;

let content = Content::from_bytes(b"Hello, World!");
let swhid = content.swhid();
println!("Content SWHID: {}", swhid);

let dir = DiskDirectoryBuilder::new(Path::new("/path/to/directory"));
let swhid = dir.swhid()?;
println!("Directory SWHID: {}", swhid);

# Ok::<_, Box<dyn std::error::Error>>(())

Creating a qualified SWHID

use swhid::{ByteRange, LineRange, Swhid, QualifiedSwhid};

let core: Swhid = "swh:1:cnt:...".parse()?;
let qualified = QualifiedSwhid::new(core)
    .with_origin("https://github.com/user/repo")
    .with_path("/src/main.rs")
    .with_lines(LineRange { start: 10, end: Some(20) })
    .with_bytes(ByteRange { start: 100, end: Some(200) });

println!("Qualified SWHID: {}", qualified);
// Output: swh:1:cnt:...;origin=https://github.com/user/repo;path=/src/main.rs;lines=10-20;bytes=100-200

# Ok::<_, Box<dyn std::error::Error>>(())

VCS Integration (Git Feature)

use std::path::PathBuf;

#[cfg(feature = "git")]
{
    use swhid::git;

    let repo = git::open_repo(&PathBuf::from("/path/to/git/repo"))?;

    // Get HEAD commit SWHID v1.2
    let head_commit = git::get_head_commit(&repo)?;
    let revision_swhid = git::revision_swhid(&repo, &head_commit)?;

    // Get tag SWHID v1.2
    let tag_oid = repo.refname_to_id("refs/tags/v1.0.0")?;
    let release_swhid = git::release_swhid(&repo, &tag_oid)?;

    // Get snapshot SWHID v1.2
    let snapshot_swhid = git::snapshot_swhid(&repo)?;
}

# Ok::<_, Box<dyn std::error::Error>>(())

CLI Tool

# Content SWHIDs
swhid content --file README.md
echo "Hello, World!" | swhid content

# Directory SWHIDs
swhid dir .
swhid dir --exclude .tmp --exclude .log /path/to/project

# VCS SWHIDs (requires --features git)
swhid git revision /path/to/git/repo [COMMIT]
swhid git release /path/to/git/repo v1.0.0
swhid git snapshot /path/to/git/repo
swhid git tags /path/to/git/repo

# Parse and validate SWHIDs
swhid parse 'swh:1:cnt:e69de29bb2d1d6434b8b29ae775ad8c2e48c5391'
swhid parse 'swh:1:dir:...;origin=https://github.com/user/repo;path=/src/main.rs;lines=10-20'

# Verify SWHIDs
swhid verify README.md 'swh:1:cnt:...'

License

Licensed under MIT.

References

Commit count: 93

cargo fmt