Skip to content

Commit

Permalink
add author parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
yoshuawuyts committed Dec 4, 2024
1 parent 7f932c5 commit 06f9aa0
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 41 deletions.
2 changes: 1 addition & 1 deletion crates/wasm-encoder/src/core/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::borrow::Cow;
use crate::{encoding_size, Encode, Section, SectionId};

/// A custom section holding arbitrary data.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq)]
pub struct CustomSection<'a> {
/// The name of this custom section.
pub name: Cow<'a, str>,
Expand Down
8 changes: 7 additions & 1 deletion crates/wasm-metadata/src/add_metadata.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{rewrite_wasm, Producers, RegistryMetadata};
use crate::{rewrite_wasm, Author, Producers, RegistryMetadata};

use anyhow::Result;

Expand All @@ -25,6 +25,11 @@ pub struct AddMetadata {
#[cfg_attr(feature="clap", clap(long, value_parser = parse_key_value, value_name="NAME=VERSION"))]
pub sdk: Vec<(String, String)>,

/// Contact details of the people or organization responsible,
/// encoded as a freeform string.
#[cfg_attr(feature = "clap", clap(long, value_name = "NAME"))]
pub author: Option<Author>,

/// Add an registry metadata to the registry-metadata section
#[cfg_attr(feature="clap", clap(long, value_parser = parse_registry_metadata_value, value_name="PATH"))]
pub registry_metadata: Option<RegistryMetadata>,
Expand Down Expand Up @@ -54,6 +59,7 @@ impl AddMetadata {
rewrite_wasm(
&self.name,
&Producers::from_meta(self),
&self.author,
self.registry_metadata.as_ref(),
input,
)
Expand Down
7 changes: 7 additions & 0 deletions crates/wasm-metadata/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ impl Metadata {
.expect("non-empty metadata stack")
.set_registry_metadata(registry);
}
KnownCustom::Unknown if c.name() == "author" => {
let a = Author::parse_custom_section(&c)?;
match metadata.last_mut().expect("non-empty metadata stack") {
Metadata::Module { author, .. } => *author = Some(a),
Metadata::Component { author, .. } => *author = Some(a),
}
}
_ => {}
},
_ => {}
Expand Down
67 changes: 41 additions & 26 deletions crates/wasm-metadata/src/oci_annotations/author.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,17 @@
use std::borrow::Cow;
use std::fmt::{self, Display};
use std::str::FromStr;

use anyhow::{ensure, Result};
use anyhow::{ensure, Error, Result};
use serde::Serialize;
use wasm_encoder::{ComponentSection, CustomSection, Encode};
use wasm_encoder::{ComponentSection, CustomSection, Encode, Section};
use wasmparser::CustomSectionReader;

/// Contact details of the people or organization responsible for the image
/// Contact details of the people or organization responsible,
/// encoded as a freeform string.
#[derive(Debug)]
#[derive(Debug, Clone, PartialEq)]
pub struct Author(CustomSection<'static>);

impl Serialize for Author {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}

impl Display for Author {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// NOTE: this will never panic since we always guarantee the data is
// encoded as utf8, even if we internally store it as [u8].
let data = String::from_utf8(self.0.data.to_vec()).unwrap();
write!(f, "{data}")
}
}

impl Author {
/// Create a new instance of `Author`.
pub fn new<S: Into<Cow<'static, str>>>(s: S) -> Self {
Expand All @@ -42,19 +25,51 @@ impl Author {
}

/// Parse an `author` custom section from a wasm binary.
pub fn parse_wasm(reader: CustomSectionReader<'_>) -> Result<Self> {
pub(crate) fn parse_custom_section(reader: &CustomSectionReader<'_>) -> Result<Self> {
ensure!(
dbg!(reader.name()) == "author",
reader.name() == "author",
"The `author` custom section should have a name of 'author'"
);
let data = String::from_utf8(reader.data().to_owned())?;
Ok(Self::new(data))
}
}

impl FromStr for Author {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::new(s.to_owned()))
}
}

impl Serialize for Author {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}

impl Display for Author {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// NOTE: this will never panic since we always guarantee the data is
// encoded as utf8, even if we internally store it as [u8].
let data = String::from_utf8(self.0.data.to_vec()).unwrap();
write!(f, "{data}")
}
}

impl ComponentSection for Author {
fn id(&self) -> u8 {
self.0.id()
ComponentSection::id(&self.0)
}
}

impl Section for Author {
fn id(&self) -> u8 {
Section::id(&self.0)
}
}

Expand All @@ -79,7 +94,7 @@ mod test {
let mut parsed = false;
for section in wasmparser::Parser::new(0).parse_all(&component) {
if let Payload::CustomSection(reader) = section.unwrap() {
let author = Author::parse_wasm(reader).unwrap();
let author = Author::parse_custom_section(&reader).unwrap();
assert_eq!(author.to_string(), "Nori Cat");
parsed = true;
}
Expand Down
2 changes: 1 addition & 1 deletion crates/wasm-metadata/src/producers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ impl Producers {
/// Merge into an existing wasm module. Rewrites the module with this producers section
/// merged into its existing one, or adds this producers section if none is present.
pub fn add_to_wasm(&self, input: &[u8]) -> Result<Vec<u8>> {
rewrite_wasm(&None, self, None, input)
rewrite_wasm(&None, self, &None, None, input)
}

pub(crate) fn display(&self, f: &mut fmt::Formatter, indent: usize) -> fmt::Result {
Expand Down
2 changes: 1 addition & 1 deletion crates/wasm-metadata/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl RegistryMetadata {
/// Merge into an existing wasm module. Rewrites the module with this registry-metadata section
/// overwriting its existing one, or adds this registry-metadata section if none is present.
pub fn add_to_wasm(&self, input: &[u8]) -> Result<Vec<u8>> {
rewrite_wasm(&None, &Producers::empty(), Some(&self), input)
rewrite_wasm(&None, &Producers::empty(), &None, Some(&self), input)
}

/// Parse a Wasm binary and extract the `Registry` section, if there is any.
Expand Down
13 changes: 12 additions & 1 deletion crates/wasm-metadata/src/rewrite.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{ComponentNames, ModuleNames, Producers, RegistryMetadata};
use crate::{Author, ComponentNames, ModuleNames, Producers, RegistryMetadata};
use anyhow::Result;
use std::borrow::Cow;
use std::mem;
Expand All @@ -9,6 +9,7 @@ use wasmparser::{KnownCustom, Parser, Payload::*};
pub(crate) fn rewrite_wasm(
add_name: &Option<String>,
add_producers: &Producers,
add_author: &Option<Author>,
add_registry_metadata: Option<&RegistryMetadata>,
input: &[u8],
) -> Result<Vec<u8>> {
Expand Down Expand Up @@ -90,6 +91,13 @@ pub(crate) fn rewrite_wasm(
continue;
}
}
KnownCustom::Unknown if c.name() == "author" => {
if add_author.is_none() {
let author = Author::parse_custom_section(c)?;
author.append_to(&mut output);
continue;
}
}
_ => {}
}
}
Expand Down Expand Up @@ -119,6 +127,9 @@ pub(crate) fn rewrite_wasm(
// Encode into output:
producers.section().append_to(&mut output);
}
if let Some(author) = add_author {
author.append_to(&mut output);
}
if add_registry_metadata.is_some() {
let registry_metadata = wasm_encoder::CustomSection {
name: Cow::Borrowed("registry-metadata"),
Expand Down
16 changes: 9 additions & 7 deletions crates/wasm-metadata/tests/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ fn add_to_empty_component() {
language: vec![("bar".to_owned(), "1.0".to_owned())],
processed_by: vec![("baz".to_owned(), "1.0".to_owned())],
sdk: vec![],
author: Some(Author::new("Chashu Cat")),
registry_metadata: Some(RegistryMetadata {
authors: Some(vec!["foo".to_owned()]),
description: Some("foo bar baz".to_owned()),
Expand Down Expand Up @@ -58,6 +59,8 @@ fn add_to_empty_component() {
"1.0"
);

assert_eq!(author.unwrap(), Author::new("Chashu Cat"));

let registry_metadata = registry_metadata.unwrap();

assert!(registry_metadata.validate().is_ok());
Expand Down Expand Up @@ -99,10 +102,8 @@ fn add_to_empty_component() {
vec!["Tools".to_owned()]
);

assert!(author.is_none());

assert_eq!(range.start, 0);
assert_eq!(range.end, 435);
assert_eq!(range.end, 454);
}
_ => panic!("metadata should be component"),
}
Expand All @@ -117,6 +118,7 @@ fn add_to_nested_component() {
language: vec![("bar".to_owned(), "1.0".to_owned())],
processed_by: vec![("baz".to_owned(), "1.0".to_owned())],
sdk: vec![],
author: Some(Author::new("Chashu Cat")),
registry_metadata: Some(RegistryMetadata {
authors: Some(vec!["Foo".to_owned()]),
..Default::default()
Expand Down Expand Up @@ -177,16 +179,16 @@ fn add_to_nested_component() {
"1.0"
);

assert_eq!(author, &Some(Author::new("Chashu Cat")));

let registry_metadata = registry_metadata.as_ref().unwrap();
assert_eq!(
registry_metadata.authors.as_ref().unwrap(),
&["Foo".to_owned()]
);

assert!(author.is_none());

assert_eq!(range.start, 10);
assert_eq!(range.end, 123);
assert_eq!(range.start, 11);
assert_eq!(range.end, 143);
}
_ => panic!("child is a module"),
}
Expand Down
7 changes: 4 additions & 3 deletions crates/wasm-metadata/tests/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ fn add_to_empty_module() {
language: vec![("bar".to_owned(), "1.0".to_owned())],
processed_by: vec![("baz".to_owned(), "1.0".to_owned())],
sdk: vec![],
author: Some(Author::new("Chashu Cat")),
registry_metadata: Some(RegistryMetadata {
authors: Some(vec!["foo".to_owned()]),
description: Some("foo bar baz".to_owned()),
Expand Down Expand Up @@ -56,6 +57,8 @@ fn add_to_empty_module() {
"1.0"
);

assert_eq!(author.unwrap(), Author::new("Chashu Cat"));

let registry_metadata = registry_metadata.unwrap();

assert!(registry_metadata.validate().is_ok());
Expand Down Expand Up @@ -97,10 +100,8 @@ fn add_to_empty_module() {
vec!["Tools".to_owned()]
);

assert!(author.is_none());

assert_eq!(range.start, 0);
assert_eq!(range.end, 425);
assert_eq!(range.end, 444);
}
_ => panic!("metadata should be module"),
}
Expand Down

0 comments on commit 06f9aa0

Please sign in to comment.