Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 50 additions & 4 deletions crates/wit-encoder/src/package.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::fmt;
use std::ops::{Deref, DerefMut};

use semver::Version;

Expand Down Expand Up @@ -58,11 +59,9 @@ impl Package {
pub fn items_mut(&mut self) -> &mut Vec<PackageItem> {
&mut self.items
}
}

impl Render for Package {
fn render(&self, f: &mut fmt::Formatter<'_>, opts: &RenderOpts) -> fmt::Result {
write!(f, "{}package {};\n", opts.spaces(), self.name)?;
/// Render the items of the package, without any package declaration.
fn render_items(&self, f: &mut fmt::Formatter<'_>, opts: &RenderOpts) -> fmt::Result {
for item in &self.items {
write!(f, "\n")?;
match item {
Expand All @@ -89,12 +88,59 @@ impl Render for Package {
}
}

impl Render for Package {
fn render(&self, f: &mut fmt::Formatter<'_>, opts: &RenderOpts) -> fmt::Result {
write!(f, "{}package {};\n", opts.spaces(), self.name)?;
self.render_items(f, opts)
}
}

impl fmt::Display for Package {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.render(f, &RenderOpts::default())
}
}

/// A variant of [`Package`] that's rendered with a nested syntax.
pub struct NestedPackage(Package);

/// Provide associated functions explicitly.
/// [`Package`] instance methods are provided via the [`Deref`] and [`DerefMut`] traits.
impl NestedPackage {
/// Create a new instance of `NestedPackage`.
pub fn new(name: PackageName) -> Self {
Self(Package::new(name))
}
}

impl Deref for NestedPackage {
type Target = Package;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl DerefMut for NestedPackage {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl Render for NestedPackage {
fn render(&self, f: &mut fmt::Formatter<'_>, opts: &RenderOpts) -> fmt::Result {
write!(f, "{}package {} {{\n", opts.spaces(), self.0.name)?;
self.0.render_items(f, &opts.indent())?;
write!(f, "{}}}\n", opts.spaces())
}
}

impl fmt::Display for NestedPackage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.render(f, &RenderOpts::default())
}
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
Expand Down
18 changes: 18 additions & 0 deletions crates/wit-encoder/tests/nested-package.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use pretty_assertions::assert_eq;
use wit_encoder::{Interface, NestedPackage, PackageName};

const PACKAGE: &str = indoc::indoc! {"
package foo:bar {

interface baz {}
}
"};

#[test]
fn concrete_types() {
let mut package = NestedPackage::new(PackageName::new("foo", "bar", None));

package.interface(Interface::new("baz"));

assert_eq!(package.to_string(), PACKAGE);
}
Loading