wasm_metadata/oci_annotations/
description.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 Description(CustomSection<'static>);
13
14impl Description {
15 pub fn new<S: Into<Cow<'static, str>>>(s: S) -> Self {
17 Self(CustomSection {
18 name: "description".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() == "description",
30 "The `description` custom section should have a name of 'description'"
31 );
32 let data = String::from_utf8(reader.data().to_owned())?;
33 Ok(Self::new(data))
34 }
35}
36
37impl FromStr for Description {
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 Description {
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 Description {
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 Description {
64 fn id(&self) -> u8 {
65 ComponentSection::id(&self.0)
66 }
67}
68
69impl Section for Description {
70 fn id(&self) -> u8 {
71 Section::id(&self.0)
72 }
73}
74
75impl Encode for Description {
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(&Description::new("Nori likes chicken"));
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 description = Description::parse_custom_section(&reader).unwrap();
97 assert_eq!(description.to_string(), "Nori likes chicken");
98 parsed = true;
99 }
100 }
101 assert!(parsed);
102 }
103
104 #[test]
105 fn serialize() {
106 let description = Description::new("Chashu likes tuna");
107 let json = serde_json::to_string(&description).unwrap();
108 assert_eq!(r#""Chashu likes tuna""#, json);
109 }
110}