wasm_metadata/oci_annotations/
revision.rs1use std::borrow::Cow;
2use std::fmt::{self, Display};
3use std::str::FromStr;
4
5use anyhow::{ensure, Error, Result};
6use serde::Serialize;
7use wasm_encoder::{ComponentSection, CustomSection, Encode, Section};
8use wasmparser::CustomSectionReader;
9
10#[derive(Debug, Clone, PartialEq)]
12pub struct Revision(CustomSection<'static>);
13
14impl Revision {
15 pub fn new<S: Into<Cow<'static, str>>>(s: S) -> Self {
17 Self(CustomSection {
18 name: "revision".into(),
19 data: match s.into() {
20 Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()),
21 Cow::Owned(s) => Cow::Owned(s.into()),
22 },
23 })
24 }
25
26 pub(crate) fn parse_custom_section(reader: &CustomSectionReader<'_>) -> Result<Self> {
28 ensure!(
29 reader.name() == "revision",
30 "The `revision` custom section should have a name of 'revision'"
31 );
32 let data = String::from_utf8(reader.data().to_owned())?;
33 Ok(Self::new(data))
34 }
35}
36
37impl FromStr for Revision {
38 type Err = Error;
39
40 fn from_str(s: &str) -> Result<Self, Self::Err> {
41 Ok(Self::new(s.to_owned()))
42 }
43}
44
45impl Serialize for Revision {
46 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
47 where
48 S: serde::Serializer,
49 {
50 serializer.serialize_str(&self.to_string())
51 }
52}
53
54impl Display for Revision {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 let data = String::from_utf8(self.0.data.to_vec()).unwrap();
59 write!(f, "{data}")
60 }
61}
62
63impl ComponentSection for Revision {
64 fn id(&self) -> u8 {
65 ComponentSection::id(&self.0)
66 }
67}
68
69impl Section for Revision {
70 fn id(&self) -> u8 {
71 Section::id(&self.0)
72 }
73}
74
75impl Encode for Revision {
76 fn encode(&self, sink: &mut Vec<u8>) {
77 self.0.encode(sink);
78 }
79}
80
81#[cfg(test)]
82mod test {
83 use super::*;
84 use wasm_encoder::Component;
85 use wasmparser::Payload;
86
87 #[test]
88 fn roundtrip() {
89 let mut component = Component::new();
90 component.section(&Revision::new("de978e17a80c1118f606fce919ba9b7d5a04a5ad"));
91 let component = component.finish();
92
93 let mut parsed = false;
94 for section in wasmparser::Parser::new(0).parse_all(&component) {
95 if let Payload::CustomSection(reader) = section.unwrap() {
96 let revision = Revision::parse_custom_section(&reader).unwrap();
97 assert_eq!(
98 revision.to_string(),
99 "de978e17a80c1118f606fce919ba9b7d5a04a5ad"
100 );
101 parsed = true;
102 }
103 }
104 assert!(parsed);
105 }
106
107 #[test]
108 fn serialize() {
109 let revision = Revision::new("de978e17a80c1118f606fce919ba9b7d5a04a5ad");
110 let json = serde_json::to_string(&revision).unwrap();
111 assert_eq!(r#""de978e17a80c1118f606fce919ba9b7d5a04a5ad""#, json);
112 }
113}