summaryrefslogtreecommitdiff
path: root/src/docker.rs
diff options
context:
space:
mode:
authorJesper Jensen <jesper@jnsn.dev>2026-02-06 12:45:45 +0100
committerJesper Jensen <jesper@jnsn.dev>2026-02-06 12:45:45 +0100
commit6ef619e5ec2349a1598896b40f2e9ea5d0163a4f (patch)
treeee227b58a50afa72358d0bb8c3749d6833e944ec /src/docker.rs
parent822de848fc1803dbc6032f90ef449b5b37717667 (diff)
Add tests for the parsing logic
Diffstat (limited to 'src/docker.rs')
-rw-r--r--src/docker.rs164
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);
+ }
+}