#container-image #reference #tags #digest #parser #docker #host

container_image_dist_ref

A library for parsing and validating container image references

7 releases

0.3.0 Mar 10, 2024
0.2.0 Feb 11, 2024
0.1.4 Jan 26, 2024

#192 in Unix APIs

Download history 7/week @ 2024-02-20 101/week @ 2024-03-05 35/week @ 2024-03-12 1/week @ 2024-03-26 31/week @ 2024-04-02

271 downloads per month

Apache-2.0

155KB
3.5K SLoC

Rust 2.5K SLoC // 0.1% comments Shell 793 SLoC // 0.1% comments

container_image_dist_ref

A docker/OCI image reference parser.

Crates.io docs.rs

This library is extensively tested against the authoritative image reference implementation, https://github.com/distribution/reference.

Image references follow this EBNF grammar:

reference            ::= name (":" tag )? ("@" digest )?
name                 ::= (domain "/")? path
domain               ::= host (":" port-number)?
host                 ::= domain-name | IPv4address | "[" IPv6address "]" /* see https://www.rfc-editor.org/rfc/rfc3986#appendix-A */
domain-name          ::= domain-component ("." domain-component)*
domain-component     ::= ([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])
port-number          ::= [0-9]+
path-component       ::= [a-z0-9]+ (separator [a-z0-9]+)*
path                 ::= path-component ("/" path-component)*
separator            ::= [_.] | "__" | "-"+

tag                  ::= [\w][\w.-]{0,127}

digest               ::= algorithm ":" encoded
algorithm            ::= algorithm-component (algorithm-separator algorithm-component)*
algorithm-separator  ::= [+._-]
algorithm-component  ::= [A-Za-z][A-Za-z0-9]*
encoded              ::= [a-fA-F0-9]{32,} /* At least 128 bit digest value */

identifier           ::= [a-f0-9]{64}

(This is translated from https://github.com/distribution/reference/blob/main/reference.go)

To avoid worst-case performance, image references are restricted further:

part maximum length
name 255
tag 127
digest 1024
algorithm 255

Motivation

I wanted to use distribution/reference in a rust project, but didn't want to deal with FFI into go.

Goals

  1. fidelity to the distribution/reference's parser
  2. fun optimizations!

More about these goals and design choices in ./ARCHITECTURE.md.

Benchmarks

Based on some naive benchmarking, this library achieves at least a 10x speedup compared to distribution/reference.

Running the benchmarks
#!/bin/bash
cargo bench # rust
( # go
  cd internal/reference_oracle &&
  go test -bench=.
)
Benchmarks on my machine

distribution/reference:

goos: linux
goarch: amd64
pkg: github.com/skalt/container_image_dist_ref/internal/reference_oracle
cpu: Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
BenchmarkOracleEntireTestSuite-8            9218            148438 ns/op

This crate:

entire_test_suite       time:   [5.0737 µs 5.1349 µs 5.2047 µs]
speedup = (148438 ns) / ((5.1349 µs) * (1000 ns / µs)) = 28.908

No runtime deps