diff options
| author | Jesper Jensen <jesper@jnsn.dev> | 2026-02-06 12:45:45 +0100 |
|---|---|---|
| committer | Jesper Jensen <jesper@jnsn.dev> | 2026-02-06 12:45:45 +0100 |
| commit | 6ef619e5ec2349a1598896b40f2e9ea5d0163a4f (patch) | |
| tree | ee227b58a50afa72358d0bb8c3749d6833e944ec /src/docker.rs | |
| parent | 822de848fc1803dbc6032f90ef449b5b37717667 (diff) | |
Add tests for the parsing logic
Diffstat (limited to 'src/docker.rs')
| -rw-r--r-- | src/docker.rs | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/src/docker.rs b/src/docker.rs new file mode 100644 index 0000000..3af3be5 --- /dev/null +++ b/src/docker.rs @@ -0,0 +1,164 @@ +use std::ops::Range; + +#[derive(Debug, Clone, PartialEq)] +pub struct DockerRef { + pub registry: Option<Range<usize>>, + pub image: Range<usize>, + pub tag: Option<Range<usize>>, + pub digest: Option<Range<usize>>, +} + +impl DockerRef { + pub fn parse(content: &str, chunk: &Range<usize>) -> DockerRef { + let mut string_range = chunk.clone(); + + let mut digest = None; + if let Some(idx) = content[string_range.clone()].rfind("@") { + digest = Some(string_range.start+idx+1..string_range.end); + string_range.end = string_range.start+idx; + } + + let mut tag = None; + if let Some(idx) = content[string_range.clone()].rfind(":") { + tag = Some(string_range.start+idx+1..string_range.end); + string_range.end = string_range.start+idx; + } + + let mut registry = None; + let image; + if let Some(idx) = content[string_range.clone()].find("/") { + let head = &content[string_range.clone()][..idx]; + if head.contains(":") || head.contains(".") { + registry = Some(string_range.start..string_range.start+idx); + image = string_range.start+idx+1..string_range.end; + } else { + registry = None; + image = string_range; + } + } else { + image = string_range; + } + + return DockerRef { + registry, + image, + tag, + digest, + }; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn image_only() { + let input = "nginx"; + let r = DockerRef::parse(input, &(0..input.len())); + + assert_eq!(r.registry, None); + assert_eq!(&input[r.image], "nginx"); + assert_eq!(r.tag, None); + assert_eq!(r.digest, None); + } + + #[test] + fn image_with_tag() { + let input = "nginx:1.21"; + let r = DockerRef::parse(input, &(0..input.len())); + + assert_eq!(r.registry, None); + assert_eq!(&input[r.image], "nginx"); + assert_eq!(&input[r.tag.unwrap()], "1.21"); + assert_eq!(r.digest, None); + } + + #[test] + fn image_with_org() { + let input = "myorg/nginx:1.21"; + let r = DockerRef::parse(input, &(0..input.len())); + + assert_eq!(r.registry, None); + assert_eq!(&input[r.image], "myorg/nginx"); + assert_eq!(&input[r.tag.unwrap()], "1.21"); + assert_eq!(r.digest, None); + } + + #[test] + fn registry_detected_by_dot() { + let input = "registry.io/nginx:1.21"; + let r = DockerRef::parse(input, &(0..input.len())); + + assert_eq!(&input[r.registry.unwrap()], "registry.io"); + assert_eq!(&input[r.image], "nginx"); + assert_eq!(&input[r.tag.unwrap()], "1.21"); + assert_eq!(r.digest, None); + } + + #[test] + fn registry_detected_by_port() { + let input = "localhost:5000/nginx:1.21"; + let r = DockerRef::parse(input, &(0..input.len())); + + assert_eq!(&input[r.registry.unwrap()], "localhost:5000"); + assert_eq!(&input[r.image], "nginx"); + assert_eq!(&input[r.tag.unwrap()], "1.21"); + assert_eq!(r.digest, None); + } + + #[test] + fn digest_without_tag() { + let input = "nginx@sha256:abc123"; + let r = DockerRef::parse(input, &(0..input.len())); + + assert_eq!(r.registry, None); + assert_eq!(&input[r.image], "nginx"); + assert_eq!(r.tag, None); + assert_eq!(&input[r.digest.unwrap()], "sha256:abc123"); + } + + #[test] + fn tag_and_digest() { + let input = "nginx:1.21@sha256:abc123"; + let r = DockerRef::parse(input, &(0..input.len())); + + assert_eq!(r.registry, None); + assert_eq!(&input[r.image], "nginx"); + assert_eq!(&input[r.tag.unwrap()], "1.21"); + assert_eq!(&input[r.digest.unwrap()], "sha256:abc123"); + } + + #[test] + fn full_reference() { + let input = "registry.io/myorg/nginx:1.21@sha256:abc123"; + let r = DockerRef::parse(input, &(0..input.len())); + + assert_eq!(&input[r.registry.unwrap()], "registry.io"); + assert_eq!(&input[r.image], "myorg/nginx"); + assert_eq!(&input[r.tag.unwrap()], "1.21"); + assert_eq!(&input[r.digest.unwrap()], "sha256:abc123"); + } + + #[test] + fn deep_image_path() { + let input = "registry.io/org/team/project/nginx:1.21"; + let r = DockerRef::parse(input, &(0..input.len())); + + assert_eq!(&input[r.registry.unwrap()], "registry.io"); + assert_eq!(&input[r.image], "org/team/project/nginx"); + assert_eq!(&input[r.tag.unwrap()], "1.21"); + assert_eq!(r.digest, None); + } + + #[test] + fn non_zero_offset() { + let input = "prefix registry.io/nginx:1.21 suffix"; + let r = DockerRef::parse(input, &(7..29)); + + assert_eq!(&input[r.registry.unwrap()], "registry.io"); + assert_eq!(&input[r.image], "nginx"); + assert_eq!(&input[r.tag.unwrap()], "1.21"); + assert_eq!(r.digest, None); + } +} |
