Repository: bytecodealliance/wasm-tools
Pull request #1703 (2024-07-29 16:37:58)

converter from wit-parser Resolve to wit-encoder packages
Also improves the interface `use` api

alexcrichton: I think the test might be due to line endings, so perhaps having it as an in-file literal instead?
MendyBerger: @alexcrichton can confirm that line endings are indeed the problem here.
How do you feel about a manual `.replace("\r\n", "\n")`? I don't think that `wit-parser` can just read text without a file.
alexcrichton: Would [`Resolve::push_str`](https://docs.rs/wit-parser/latest/wit_parser/struct.Resolve.html#method.push_str) work for that?
MendyBerger: Missed that one. Should work!

Patch:
diff --git a/Cargo.lock b/Cargo.lock
index d74f3140..11b4a116 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -53,9 +53,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
 
 [[package]]
 name = "anstream"
-version = "0.6.14"
+version = "0.6.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
+checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
 dependencies = [
  "anstyle",
  "anstyle-parse",
@@ -68,33 +68,33 @@ dependencies = [
 
 [[package]]
 name = "anstyle"
-version = "1.0.7"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
+checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
 
 [[package]]
 name = "anstyle-parse"
-version = "0.2.4"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
+checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
 dependencies = [
  "utf8parse",
 ]
 
 [[package]]
 name = "anstyle-query"
-version = "1.1.0"
+version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
+checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
 dependencies = [
  "windows-sys",
 ]
 
 [[package]]
 name = "anstyle-wincon"
-version = "3.0.3"
+version = "3.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
+checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
 dependencies = [
  "anstyle",
  "windows-sys",
@@ -117,9 +117,9 @@ dependencies = [
 
 [[package]]
 name = "arrayref"
-version = "0.3.7"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
+checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a"
 
 [[package]]
 name = "arrayvec"
@@ -156,9 +156,9 @@ dependencies = [
 
 [[package]]
 name = "blake3"
-version = "1.5.1"
+version = "1.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52"
+checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210"
 dependencies = [
  "arrayref",
  "arrayvec",
@@ -187,13 +187,12 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
 
 [[package]]
 name = "cc"
-version = "1.0.101"
+version = "1.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac367972e516d45567c7eafc73d24e1c193dcf200a8d94e9db7b3d38b349572d"
+checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f"
 dependencies = [
  "jobserver",
  "libc",
- "once_cell",
 ]
 
 [[package]]
@@ -231,9 +230,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.7"
+version = "4.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f"
+checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -241,9 +240,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.7"
+version = "4.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f"
+checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa"
 dependencies = [
  "anstream",
  "anstyle",
@@ -253,18 +252,18 @@ dependencies = [
 
 [[package]]
 name = "clap_complete"
-version = "4.5.6"
+version = "4.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbca90c87c2a04da41e95d1856e8bcd22f159bdbfa147314d2ce5218057b0e58"
+checksum = "c6ae69fbb0833c6fcd5a8d4b8609f108c7ad95fc11e248d853ff2c42a90df26a"
 dependencies = [
  "clap",
 ]
 
 [[package]]
 name = "clap_derive"
-version = "4.5.5"
+version = "4.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6"
+checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e"
 dependencies = [
  "heck 0.5.0",
  "proc-macro2",
@@ -274,9 +273,9 @@ dependencies = [
 
 [[package]]
 name = "clap_lex"
-version = "0.7.1"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
+checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
 
 [[package]]
 name = "cobs"
@@ -286,9 +285,9 @@ checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
 
 [[package]]
 name = "colorchoice"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
+checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
 
 [[package]]
 name = "component"
@@ -509,17 +508,6 @@ dependencies = [
  "syn",
 ]
 
-[[package]]
-name = "derive_more"
-version = "0.99.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
 [[package]]
 name = "diff"
 version = "0.1.13"
@@ -567,9 +555,9 @@ dependencies = [
 
 [[package]]
 name = "env_filter"
-version = "0.1.0"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea"
+checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab"
 dependencies = [
  "log",
  "regex",
@@ -577,9 +565,9 @@ dependencies = [
 
 [[package]]
 name = "env_logger"
-version = "0.11.3"
+version = "0.11.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9"
+checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d"
 dependencies = [
  "anstream",
  "anstyle",
@@ -630,9 +618,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
 
 [[package]]
 name = "flagset"
-version = "0.4.5"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdeb3aa5e95cf9aabc17f060cfa0ced7b83f042390760ca53bf09df9968acaa1"
+checksum = "b3ea1ec5f8307826a5b71094dd91fc04d4ae75d5709b20ad351c7fb4815c86ec"
 dependencies = [
  "serde",
 ]
@@ -841,9 +829,9 @@ dependencies = [
 
 [[package]]
 name = "is_terminal_polyfill"
-version = "1.70.0"
+version = "1.70.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
 
 [[package]]
 name = "itertools"
@@ -880,9 +868,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
 
 [[package]]
 name = "jobserver"
-version = "0.1.31"
+version = "0.1.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
+checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
 dependencies = [
  "libc",
 ]
@@ -1051,9 +1039,9 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.36.0"
+version = "0.36.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434"
+checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
 dependencies = [
  "crc32fast",
  "flate2",
@@ -1071,9 +1059,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 
 [[package]]
 name = "oorandom"
-version = "11.1.3"
+version = "11.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
+checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
 
 [[package]]
 name = "paste"
@@ -1273,12 +1261,11 @@ dependencies = [
 
 [[package]]
 name = "ruzstd"
-version = "0.6.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5174a470eeb535a721ae9fdd6e291c2411a906b96592182d05217591d5c5cf7b"
+checksum = "5022b253619b1ba797f243056276bed8ed1a73b0f5a7ce7225d524067644bf8f"
 dependencies = [
  "byteorder",
- "derive_more",
  "twox-hash",
 ]
 
@@ -1308,18 +1295,18 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.203"
+version = "1.0.204"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
+checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.203"
+version = "1.0.204"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
+checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1328,9 +1315,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.118"
+version = "1.0.120"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
+checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
 dependencies = [
  "itoa",
  "ryu",
@@ -1416,9 +1403,9 @@ checksum = "7c68d531d83ec6c531150584c42a4290911964d5f0d79132b193b67252a23b71"
 
 [[package]]
 name = "syn"
-version = "2.0.68"
+version = "2.0.72"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9"
+checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1427,9 +1414,9 @@ dependencies = [
 
 [[package]]
 name = "target-lexicon"
-version = "0.12.14"
+version = "0.12.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
+checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2"
 
 [[package]]
 name = "tempfile"
@@ -1454,18 +1441,18 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.61"
+version = "1.0.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
+checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.61"
+version = "1.0.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
+checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1545,9 +1532,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
 
 [[package]]
 name = "version_check"
-version = "0.9.4"
+version = "0.9.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
 
 [[package]]
 name = "walkdir"
@@ -2119,9 +2106,9 @@ dependencies = [
 
 [[package]]
 name = "windows-targets"
-version = "0.52.5"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
 dependencies = [
  "windows_aarch64_gnullvm",
  "windows_aarch64_msvc",
@@ -2135,51 +2122,51 @@ dependencies = [
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.52.5"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.52.5"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.52.5"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
 
 [[package]]
 name = "windows_i686_gnullvm"
-version = "0.52.5"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.52.5"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.52.5"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.52.5"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.52.5"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 
 [[package]]
 name = "wit-bindgen-rt"
@@ -2219,10 +2206,12 @@ dependencies = [
 name = "wit-encoder"
 version = "0.215.0"
 dependencies = [
+ "id-arena",
  "indoc",
  "pretty_assertions",
  "semver",
  "serde",
+ "wit-parser 0.215.0",
 ]
 
 [[package]]
@@ -2297,18 +2286,18 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
 
 [[package]]
 name = "zerocopy"
-version = "0.7.34"
+version = "0.7.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
 dependencies = [
  "zerocopy-derive",
 ]
 
 [[package]]
 name = "zerocopy-derive"
-version = "0.7.34"
+version = "0.7.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/Cargo.toml b/Cargo.toml
index 9cdd5ad6..05102856 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -94,6 +94,7 @@ ahash = { version = "0.8.11", default-features = false }
 termcolor = "1.2.0"
 indoc = "2.0.5"
 gimli = "0.30.0"
+id-arena = "2"
 
 wasm-compose = { version = "0.215.0", path = "crates/wasm-compose" }
 wasm-encoder = { version = "0.215.0", path = "crates/wasm-encoder" }
diff --git a/crates/wit-encoder/Cargo.toml b/crates/wit-encoder/Cargo.toml
index 626959e6..1f8a0700 100644
--- a/crates/wit-encoder/Cargo.toml
+++ b/crates/wit-encoder/Cargo.toml
@@ -11,7 +11,7 @@ version.workspace = true
 workspace = true
 
 [features]
-default = ["serde"]
+default = ["serde", "from-parser"]
 
 # Enables JSON serialization/deserialization of the wit-encoder structures.
 
@@ -23,11 +23,14 @@ default = ["serde"]
 # *Note*: The exact structure of the JSON is likely not going to be very stable over time,
 # so slight tweaks and variants should be expected as this crate evolves.
 serde = ["dep:serde", "semver/serde"]
+from-parser = ["wit-parser", "id-arena"]
 
 [dependencies]
 semver = { workspace = true }
 pretty_assertions = { workspace = true }
 serde = { workspace = true, optional = true, features = ["derive"] }
+wit-parser = { workspace = true, optional = true }
+id-arena = { workspace = true, optional = true }
 
 [dev-dependencies]
 indoc = { workspace = true }
diff --git a/crates/wit-encoder/src/from_parser.rs b/crates/wit-encoder/src/from_parser.rs
new file mode 100644
index 00000000..a9306c6f
--- /dev/null
+++ b/crates/wit-encoder/src/from_parser.rs
@@ -0,0 +1,506 @@
+use id_arena::Id;
+
+use crate::{
+    Enum, Flags, Interface, InterfaceItem, Package, PackageName, Params, Record, Resource,
+    ResourceFunc, Result_, Results, StandaloneFunc, Tuple, Type, TypeDef, TypeDefKind, Variant,
+    World, WorldItem,
+};
+
+pub fn packages_from_parsed(resolve: &wit_parser::Resolve) -> Vec<Package> {
+    let converter = Converter::new(resolve);
+    converter.convert()
+}
+
+struct Converter<'a> {
+    resolve: &'a wit_parser::Resolve,
+}
+
+impl<'a> Converter<'a> {
+    fn new(resolve: &'a wit_parser::Resolve) -> Self {
+        Self { resolve }
+    }
+
+    fn convert(&self) -> Vec<Package> {
+        self.resolve
+            .packages
+            .iter()
+            .map(|(_, p)| self.convert_package(p))
+            .collect()
+    }
+
+    fn convert_package(&self, package: &wit_parser::Package) -> Package {
+        let mut output = Package::new(self.convert_package_name(&package.name));
+        for (_, id) in &package.interfaces {
+            let interface = self.resolve.interfaces.get(*id).unwrap();
+            output.interface(self.convert_interface(
+                interface,
+                None,
+                wit_parser::TypeOwner::Interface(*id),
+            ));
+        }
+        for (_, id) in &package.worlds {
+            let world = self.resolve.worlds.get(*id).unwrap();
+            output.world(self.convert_world(world, wit_parser::TypeOwner::World(*id)));
+        }
+        output
+    }
+
+    fn convert_package_name(&self, package: &wit_parser::PackageName) -> PackageName {
+        PackageName::new(
+            package.namespace.clone(),
+            package.name.clone(),
+            package.version.clone(),
+        )
+    }
+
+    fn convert_world(&self, world: &wit_parser::World, owner: wit_parser::TypeOwner) -> World {
+        let mut output = World::new(world.name.clone());
+
+        for (key, item) in &world.imports {
+            match item {
+                wit_parser::WorldItem::Interface { id, .. } => {
+                    let interface = self.resolve.interfaces.get(*id).unwrap();
+                    output.item(match &interface.name {
+                        Some(name) => {
+                            // standalone
+                            WorldItem::named_interface_import(name.clone())
+                        }
+                        None => {
+                            // inlined
+                            let name = match key {
+                                wit_parser::WorldKey::Name(name) => name.clone(),
+                                wit_parser::WorldKey::Interface(_) => {
+                                    unreachable!("inlined interface must have a kye name")
+                                }
+                            };
+                            WorldItem::inline_interface_import(self.convert_interface(
+                                interface,
+                                Some(name),
+                                owner,
+                            ))
+                        }
+                    });
+                }
+                wit_parser::WorldItem::Function(func) => {
+                    if let Some(func) = self.standalone_func_convert(func) {
+                        output.item(WorldItem::function_import(func));
+                    }
+                }
+                wit_parser::WorldItem::Type(_) => {
+                    todo!();
+                }
+            }
+        }
+        for (key, item) in &world.exports {
+            match item {
+                wit_parser::WorldItem::Interface { id, .. } => {
+                    let interface = self.resolve.interfaces.get(*id).unwrap();
+                    output.item(match &interface.name {
+                        Some(name) => {
+                            // standalone
+                            WorldItem::named_interface_export(name.clone())
+                        }
+                        None => {
+                            // inlined
+                            let name = match key {
+                                wit_parser::WorldKey::Name(name) => name.clone(),
+                                wit_parser::WorldKey::Interface(_) => {
+                                    unreachable!("inlined interface must have a kye name")
+                                }
+                            };
+                            WorldItem::inline_interface_export(self.convert_interface(
+                                interface,
+                                Some(name),
+                                owner,
+                            ))
+                        }
+                    });
+                }
+                wit_parser::WorldItem::Function(func) => {
+                    if let Some(func) = self.standalone_func_convert(func) {
+                        output.item(WorldItem::function_export(func));
+                    }
+                }
+                wit_parser::WorldItem::Type(_) => {
+                    todo!();
+                }
+            }
+        }
+
+        output
+    }
+
+    fn convert_interface(
+        &self,
+        interface: &wit_parser::Interface,
+        inlined_name: Option<String>,
+        owner: wit_parser::TypeOwner,
+    ) -> Interface {
+        let mut output = Interface::new(interface.name.clone().unwrap_or_else(|| {
+            inlined_name
+                .clone()
+                .expect("inlined interface must pass in inlined_name")
+        }));
+
+        for (_, func) in &interface.functions {
+            if let Some(func) = self.standalone_func_convert(func) {
+                output.items.push(InterfaceItem::Function(func));
+            }
+        }
+        for (_, type_id) in &interface.types {
+            let type_def = self.resolve.types.get(*type_id).unwrap();
+
+            let underlying_type_def = match &type_def.kind {
+                wit_parser::TypeDefKind::Type(type_) => match &type_ {
+                    wit_parser::Type::Id(type_id) => {
+                        let type_def = self.resolve.types.get(*type_id).unwrap();
+                        type_def
+                    }
+                    _ => type_def,
+                },
+                _ => type_def,
+            };
+
+            if underlying_type_def.owner == owner {
+                if let Some(type_def) = self.convert_type_def(type_def, *type_id) {
+                    output.item(InterfaceItem::TypeDef(type_def));
+                }
+            } else {
+                let interface_name = match underlying_type_def.owner {
+                    wit_parser::TypeOwner::Interface(id) => self
+                        .resolve
+                        .interfaces
+                        .get(id)
+                        .unwrap()
+                        .name
+                        .clone()
+                        .expect("can't use type from inline interface"),
+                    _ => panic!("Type not part of an interface"),
+                };
+                let local_type_name = type_def.name.clone().unwrap();
+                let underlying_local_type_name = underlying_type_def.name.clone().unwrap();
+                if underlying_local_type_name == local_type_name {
+                    output.use_type(interface_name, local_type_name, None);
+                } else {
+                    output.use_type(
+                        interface_name,
+                        underlying_local_type_name,
+                        Some(local_type_name.into()),
+                    );
+                }
+            }
+        }
+
+        output
+    }
+
+    fn convert_type_def(
+        &self,
+        type_def: &wit_parser::TypeDef,
+        type_def_id: Id<wit_parser::TypeDef>,
+    ) -> Option<TypeDef> {
+        match &type_def.name {
+            None => None,
+            Some(name) => {
+                let kind = match &type_def.kind {
+                    wit_parser::TypeDefKind::Record(record) => {
+                        let output = self.convert_record(record);
+                        TypeDefKind::Record(output)
+                    }
+                    wit_parser::TypeDefKind::Resource => {
+                        let output = self.convert_resource(type_def_id, name, &type_def.owner);
+                        TypeDefKind::Resource(output)
+                    }
+                    wit_parser::TypeDefKind::Flags(flags) => {
+                        let output = self.convert_flags(flags);
+                        TypeDefKind::Flags(output)
+                    }
+                    wit_parser::TypeDefKind::Variant(variant) => {
+                        let output = self.convert_variant(variant);
+                        TypeDefKind::Variant(output)
+                    }
+                    wit_parser::TypeDefKind::Enum(enum_) => {
+                        let output = self.convert_enum(enum_);
+                        TypeDefKind::Enum(output)
+                    }
+                    wit_parser::TypeDefKind::Future(_) => {
+                        todo!("Enable once wit-encoder supports `future`")
+                    }
+                    wit_parser::TypeDefKind::Stream(_) => {
+                        todo!("Enable once wit-encoder supports `stream`")
+                    }
+                    // all the following are just `type` declarations
+                    wit_parser::TypeDefKind::Option(ty) => {
+                        let output = Type::option(self.convert_type(ty));
+                        TypeDefKind::Type(output)
+                    }
+                    wit_parser::TypeDefKind::List(ty) => {
+                        let output = Type::list(self.convert_type(ty));
+                        TypeDefKind::Type(output)
+                    }
+                    wit_parser::TypeDefKind::Handle(handle) => {
+                        let output = self.handle_to_type(handle);
+                        TypeDefKind::Type(output)
+                    }
+                    wit_parser::TypeDefKind::Result(result) => {
+                        let output = Type::result(self.convert_result(result));
+                        TypeDefKind::Type(output)
+                    }
+                    wit_parser::TypeDefKind::Tuple(tuple) => {
+                        let output = Type::Tuple(self.convert_tuple(tuple));
+                        TypeDefKind::Type(output)
+                    }
+                    wit_parser::TypeDefKind::Type(ty) => {
+                        let output = self.convert_type(ty);
+                        TypeDefKind::Type(output)
+                    }
+                    wit_parser::TypeDefKind::Unknown => unreachable!(),
+                };
+
+                Some(TypeDef::new(name.clone(), kind))
+            }
+        }
+    }
+
+    fn convert_type(&self, type_: &wit_parser::Type) -> Type {
+        match type_ {
+            wit_parser::Type::Bool => Type::Bool,
+            wit_parser::Type::U8 => Type::U8,
+            wit_parser::Type::U16 => Type::U16,
+            wit_parser::Type::U32 => Type::U32,
+            wit_parser::Type::U64 => Type::U64,
+            wit_parser::Type::S8 => Type::S8,
+            wit_parser::Type::S16 => Type::S16,
+            wit_parser::Type::S32 => Type::S32,
+            wit_parser::Type::S64 => Type::S64,
+            wit_parser::Type::F32 => Type::F32,
+            wit_parser::Type::F64 => Type::F64,
+            wit_parser::Type::Char => Type::Char,
+            wit_parser::Type::String => Type::String,
+            wit_parser::Type::Id(id) => {
+                let type_def = self.resolve.types.get(*id).expect("Type not found");
+                match &type_def.name {
+                    Some(name) => Type::named(name.clone()),
+                    None => match &type_def.kind {
+                        wit_parser::TypeDefKind::Tuple(tuple) => {
+                            Type::Tuple(self.convert_tuple(tuple))
+                        }
+                        wit_parser::TypeDefKind::Option(type_) => {
+                            Type::option(self.convert_type(type_))
+                        }
+                        wit_parser::TypeDefKind::Result(result) => {
+                            Type::result(self.convert_result(result))
+                        }
+                        wit_parser::TypeDefKind::List(type_) => {
+                            Type::list(self.convert_type(type_))
+                        }
+                        wit_parser::TypeDefKind::Handle(handle) => self.handle_to_type(handle),
+                        wit_parser::TypeDefKind::Future(_) => {
+                            todo!("Enable once wit-encoder supports `future`")
+                        }
+                        wit_parser::TypeDefKind::Stream(_) => {
+                            todo!("Enable once wit-encoder supports `stream`")
+                        }
+                        wit_parser::TypeDefKind::Record(_)
+                        | wit_parser::TypeDefKind::Resource
+                        | wit_parser::TypeDefKind::Flags(_)
+                        | wit_parser::TypeDefKind::Variant(_)
+                        | wit_parser::TypeDefKind::Enum(_)
+                        | wit_parser::TypeDefKind::Type(_) => {
+                            panic!("type doesn't have a name, and can't be inlined")
+                        }
+                        wit_parser::TypeDefKind::Unknown => unreachable!(),
+                    },
+                }
+            }
+        }
+    }
+
+    fn convert_enum(&self, enum_: &wit_parser::Enum) -> Enum {
+        let mut output = Enum::empty();
+        for case in &enum_.cases {
+            output.case(case.name.clone())
+        }
+        output
+    }
+    fn convert_record(&self, record: &wit_parser::Record) -> Record {
+        Record::new(record.fields.iter().map(|field| {
+            let name = field.name.clone();
+            let type_ = self.convert_type(&field.ty);
+            (name, type_)
+        }))
+    }
+    fn convert_variant(&self, variant: &wit_parser::Variant) -> Variant {
+        let mut output = Variant::empty();
+        for case in &variant.cases {
+            match &case.ty {
+                Some(ty) => {
+                    let ty = self.convert_type(ty);
+                    output.case((case.name.clone(), ty))
+                }
+                None => output.case((case.name.clone(),)),
+            }
+        }
+        output
+    }
+    fn convert_flags(&self, flags: &wit_parser::Flags) -> Flags {
+        Flags::new(flags.flags.iter().map(|flag| (flag.name.clone(),)))
+    }
+
+    fn convert_resource(
+        &self,
+        resource_id: Id<wit_parser::TypeDef>,
+        name: &str,
+        owner: &wit_parser::TypeOwner,
+    ) -> Resource {
+        let functions = match owner {
+            wit_parser::TypeOwner::World(_) => {
+                todo!("Enable once win-encoder supports `include`")
+            }
+            wit_parser::TypeOwner::Interface(id) => {
+                &self.resolve.interfaces.get(*id).unwrap().functions
+            }
+            wit_parser::TypeOwner::None => panic!("Resource has to have an owner"),
+        };
+
+        let mut output = Resource::empty();
+        for (_, func) in functions {
+            if let Some(method) = self.convert_resource_func(resource_id, name, func) {
+                output.func(method);
+            }
+        }
+        output
+    }
+
+    fn convert_resource_func(
+        &self,
+        resource_id: Id<wit_parser::TypeDef>,
+        resource_name: &str,
+        func: &wit_parser::Function,
+    ) -> Option<ResourceFunc> {
+        // skip first argument for methods, as they're just `self`.
+        let mut skip_first_param = false;
+        // constructors can't return anything
+        let mut with_returns = true;
+        let mut method = match func.kind {
+            wit_parser::FunctionKind::Freestanding => return None,
+            wit_parser::FunctionKind::Method(id) => {
+                if id != resource_id {
+                    return None;
+                }
+                skip_first_param = true;
+                let name = clean_func_name(resource_name, &func.name);
+                ResourceFunc::method(name)
+            }
+            wit_parser::FunctionKind::Static(id) => {
+                if id != resource_id {
+                    return None;
+                }
+                let name = clean_func_name(resource_name, &func.name);
+                ResourceFunc::static_(name)
+            }
+            wit_parser::FunctionKind::Constructor(id) => {
+                if id != resource_id {
+                    return None;
+                }
+                with_returns = false;
+                ResourceFunc::constructor()
+            }
+        };
+
+        method.set_params(self.convert_params(&func.params));
+        if skip_first_param {
+            method.params_mut().items_mut().remove(0);
+        }
+
+        if with_returns {
+            method.set_results(self.convert_results(&func.results));
+        }
+
+        Some(method)
+    }
+
+    fn standalone_func_convert(&self, func: &wit_parser::Function) -> Option<StandaloneFunc> {
+        match func.kind {
+            wit_parser::FunctionKind::Method(_)
+            | wit_parser::FunctionKind::Static(_)
+            | wit_parser::FunctionKind::Constructor(_) => None,
+            wit_parser::FunctionKind::Freestanding => {
+                let mut output = StandaloneFunc::new(func.name.clone());
+
+                output.set_params(self.convert_params(&func.params));
+                output.set_results(self.convert_results(&func.results));
+
+                Some(output)
+            }
+        }
+    }
+
+    fn convert_params(&self, params: &wit_parser::Params) -> Params {
+        let mut output = Params::empty();
+        for (name, ty) in params.iter() {
+            let name = name.to_string();
+            let ty = self.convert_type(ty);
+            output.push(name, ty);
+        }
+        output
+    }
+
+    fn convert_results(&self, results: &wit_parser::Results) -> Results {
+        match results {
+            wit_parser::Results::Named(named) => Results::named(named.iter().map(|(name, ty)| {
+                let ty = self.convert_type(ty);
+                (name.to_owned(), ty)
+            })),
+            wit_parser::Results::Anon(ty) => Results::Anon(self.convert_type(ty)),
+        }
+    }
+
+    fn handle_to_type(&self, handle: &wit_parser::Handle) -> Type {
+        let id = match handle {
+            wit_parser::Handle::Own(id) => id,
+            wit_parser::Handle::Borrow(id) => id,
+        };
+        let type_def = self.resolve.types.get(*id).expect("Type not found");
+        let name = type_def
+            .name
+            .clone()
+            .expect("Handles should only be for resources, and resources should have names");
+        match handle {
+            wit_parser::Handle::Own(_) => Type::named(name),
+            wit_parser::Handle::Borrow(_) => Type::borrow(name),
+        }
+    }
+
+    fn convert_result(&self, result: &wit_parser::Result_) -> Result_ {
+        match (&result.ok, &result.err) {
+            (None, None) => Result_::empty(),
+            (Some(ok), None) => Result_::ok(self.convert_type(ok)),
+            (None, Some(err)) => Result_::err(self.convert_type(err)),
+            (Some(ok), Some(err)) => Result_::both(self.convert_type(ok), self.convert_type(err)),
+        }
+    }
+
+    fn convert_tuple(&self, tuple: &wit_parser::Tuple) -> Tuple {
+        let mut output = Tuple::empty();
+        for ty in tuple.types.iter() {
+            output.types_mut().push(self.convert_type(ty));
+        }
+        output
+    }
+}
+
+fn clean_func_name(resource_name: &str, method_name: &str) -> String {
+    const METHOD_PREFIX: &str = "[method]";
+    const STATIC_PREFIX: &str = "[static]";
+
+    let method_name = method_name
+        .strip_prefix(METHOD_PREFIX)
+        .unwrap_or(method_name);
+    let method_name = method_name
+        .strip_prefix(STATIC_PREFIX)
+        .unwrap_or(method_name);
+    let method_name = method_name.strip_prefix(resource_name).unwrap();
+    let method_name = method_name.strip_prefix(".").unwrap();
+    method_name.to_string()
+}
diff --git a/crates/wit-encoder/src/interface.rs b/crates/wit-encoder/src/interface.rs
index 1485bcad..46b50cb5 100644
--- a/crates/wit-encoder/src/interface.rs
+++ b/crates/wit-encoder/src/interface.rs
@@ -9,6 +9,9 @@ pub struct Interface {
     /// Name of this interface.
     pub(crate) name: Ident,
 
+    // Interface uses
+    pub(crate) uses: Vec<Use>,
+
     // Interface items
     pub(crate) items: Vec<InterfaceItem>,
 
@@ -21,6 +24,7 @@ impl Interface {
     pub fn new(name: impl Into<Ident>) -> Self {
         Self {
             name: name.into(),
+            uses: vec![],
             items: vec![],
             docs: None,
         }
@@ -38,7 +42,28 @@ impl Interface {
 
     /// Add a `Use` to the interface
     pub fn use_(&mut self, use_: Use) {
-        self.items.push(InterfaceItem::Use(use_));
+        self.uses.push(use_);
+    }
+
+    /// Use a type in the interface.
+    pub fn use_type(
+        &mut self,
+        target: impl Into<Ident>,
+        item: impl Into<Ident>,
+        rename: Option<Ident>,
+    ) {
+        let target = target.into();
+        let use_ = self.uses.iter_mut().find(|u| u.target() == &target);
+        match use_ {
+            Some(use_) => use_.item(item, rename),
+            None => {
+                self.use_({
+                    let mut use_ = Use::new(target);
+                    use_.item(item, rename);
+                    use_
+                });
+            }
+        }
     }
 
     pub fn item(&mut self, item: impl Into<InterfaceItem>) {
@@ -68,7 +93,6 @@ impl Interface {
 #[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
 pub enum InterfaceItem {
     TypeDef(TypeDef),
-    Use(Use),
     Function(StandaloneFunc),
 }
 
@@ -91,11 +115,19 @@ impl Render for InterfaceItems {
                     }
                     write!(f, ";\n")?;
                 }
-                InterfaceItem::Use(use_) => {
-                    use_.render(f, opts)?;
-                }
             }
         }
         Ok(())
     }
 }
+
+pub type InterfaceUses = Vec<Use>;
+
+impl Render for InterfaceUses {
+    fn render(&self, f: &mut fmt::Formatter<'_>, opts: &RenderOpts) -> fmt::Result {
+        for use_ in self {
+            use_.render(f, opts)?;
+        }
+        Ok(())
+    }
+}
diff --git a/crates/wit-encoder/src/lib.rs b/crates/wit-encoder/src/lib.rs
index 902ffc00..d8d9df29 100644
--- a/crates/wit-encoder/src/lib.rs
+++ b/crates/wit-encoder/src/lib.rs
@@ -6,6 +6,8 @@
 mod docs;
 mod enum_;
 mod flags;
+#[cfg(feature = "from-parser")]
+mod from_parser;
 mod function;
 mod ident;
 mod include;
@@ -24,6 +26,8 @@ mod world;
 pub use docs::*;
 pub use enum_::*;
 pub use flags::*;
+#[cfg(feature = "from-parser")]
+pub use from_parser::*;
 pub use function::*;
 pub use ident::*;
 pub use include::*;
diff --git a/crates/wit-encoder/src/package.rs b/crates/wit-encoder/src/package.rs
index 749fd650..5734548f 100644
--- a/crates/wit-encoder/src/package.rs
+++ b/crates/wit-encoder/src/package.rs
@@ -63,8 +63,9 @@ impl Render for Package {
                         docs.render(f, opts)?;
                     }
                     write!(f, "{}interface {} {{", opts.spaces(), interface.name)?;
-                    if !interface.items.is_empty() {
+                    if !interface.uses.is_empty() || !interface.items.is_empty() {
                         write!(f, "\n")?;
+                        interface.uses.render(f, &opts.indent())?;
                         interface.items.render(f, &opts.indent())?;
                         write!(f, "{}}}\n", opts.spaces())?;
                     } else {
diff --git a/crates/wit-encoder/src/use_.rs b/crates/wit-encoder/src/use_.rs
index bb549adb..edb6867c 100644
--- a/crates/wit-encoder/src/use_.rs
+++ b/crates/wit-encoder/src/use_.rs
@@ -8,7 +8,7 @@ use crate::{Ident, Render};
 #[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
 pub struct Use {
     target: Ident,
-    use_names_list: Vec<(String, Option<String>)>,
+    use_names_list: Vec<(Ident, Option<Ident>)>,
 }
 
 impl Use {
@@ -19,9 +19,18 @@ impl Use {
         }
     }
 
-    pub fn item(&mut self, id: &str, alias: Option<&str>) {
+    pub fn target(&self) -> &Ident {
+        &self.target
+    }
+
+    pub fn set_target(&mut self, target: Ident) {
+        self.target = target;
+    }
+
+    // `alias` is a concrete type because of https://github.com/rust-lang/rust/issues/36887
+    pub fn item(&mut self, id: impl Into<Ident>, alias: Option<Ident>) {
         self.use_names_list
-            .push((id.to_string(), alias.map(|s| s.to_string())));
+            .push((id.into(), alias.map(|s| s.into())));
     }
 }
 
diff --git a/crates/wit-encoder/src/world.rs b/crates/wit-encoder/src/world.rs
index 320d890c..91f419b2 100644
--- a/crates/wit-encoder/src/world.rs
+++ b/crates/wit-encoder/src/world.rs
@@ -101,8 +101,9 @@ impl Render for World {
                     }
                     import(f, opts)?;
                     write!(f, "{}: interface {{", interface.name)?;
-                    if !interface.items.is_empty() {
+                    if !interface.uses.is_empty() || !interface.items.is_empty() {
                         write!(f, "\n")?;
+                        interface.uses.render(f, &opts.indent())?;
                         interface.items.render(f, &opts.indent())?;
                         write!(f, "{}}}\n", opts.spaces())?;
                     } else {
diff --git a/crates/wit-parser/Cargo.toml b/crates/wit-parser/Cargo.toml
index 577ec4a4..29e11c46 100644
--- a/crates/wit-parser/Cargo.toml
+++ b/crates/wit-parser/Cargo.toml
@@ -17,7 +17,7 @@ rust-version.workspace = true
 workspace = true
 
 [dependencies]
-id-arena = "2"
+id-arena = { workspace = true }
 anyhow = { workspace = true }
 indexmap = { workspace = true, features = ['std'] }
 unicode-xid = "0.2.2"


Test patch:
diff --git a/crates/wit-encoder/tests/parse-to-encoder.rs b/crates/wit-encoder/tests/parse-to-encoder.rs
new file mode 100644
index 00000000..45cb39b6
--- /dev/null
+++ b/crates/wit-encoder/tests/parse-to-encoder.rs
@@ -0,0 +1,84 @@
+use pretty_assertions::assert_eq;
+use wit_encoder::packages_from_parsed;
+
+const WIT: &str = r#"package foo:functions;
+
+interface foo-interface {
+  flags %flags {
+    flag-a,
+    flag-b,
+  }
+}
+
+interface bar-interface {
+  use foo-interface.{ %flags as external-type };
+  enum some-enum {
+    first-case,
+    second-case,
+  }
+}
+
+interface %interface {
+  use bar-interface.{ some-enum, external-type };
+  statndalone-func: func(a: u32, b: s32) -> f32;
+  variant %variant {
+    empty-case,
+    valued-case(u32),
+  }
+  resource %resource {
+    constructor();
+    method: func(arg: list<u32>) -> char;
+    static-method: static func(arg: tuple<u32, u32>) -> list<u32>;
+  }
+  resource other-resource {
+    constructor(values: list<u32>);
+    static-method: func(arg: tuple<u32, u32>);
+  }
+  record some-record {
+    optinal: option<string>,
+    %own: %resource,
+    %borrow: borrow<%resource>,
+    result-a: result,
+    result-b: result<f64>,
+    result-c: result<_, f64>,
+    result-d: result<f64, f32>,
+    result-e: result<string, list<u8>>,
+  }
+  type type-list = list<f64>;
+  type type-option = option<f64>;
+  type type-result-a = result;
+  type type-result-b = result<f64>;
+  type type-result-c = result<_, f64>;
+  type type-result-d = result<f64, f32>;
+  type type-result-e = result<string, list<u8>>;
+  type type-handle-own = %resource;
+  type type-handle-borrow = borrow<%resource>;
+  type type-tuple = tuple<u32, list<u32>, borrow<%resource>>;
+}
+
+world my-world {
+  import foo-interface;
+  import bar-interface;
+  import %interface;
+  import inline-import: interface {
+    do-something: func(a: string) -> string;
+  }
+  import import-func: func();
+  export export-func: func(a: u32, b: s32) -> f32;
+  export %interface;
+  export inline-export: interface {
+    do-nothing: func();
+  }
+}
+"#;
+
+#[test]
+fn round_trip() {
+    let mut resolve = wit_parser::Resolve::new();
+    resolve.push_str("", WIT).unwrap();
+    let packages = packages_from_parsed(&resolve);
+
+    assert!(packages.len() == 1, "Should create exactly one package");
+    let package = &packages[0];
+    assert_eq!(WIT, package.to_string());
+}
diff --git a/crates/wit-encoder/tests/use.rs b/crates/wit-encoder/tests/use.rs
index c3d891c6..0f154b4c 100644
--- a/crates/wit-encoder/tests/use.rs
+++ b/crates/wit-encoder/tests/use.rs
@@ -30,7 +30,7 @@ fn concrete_types() {
 
     let mut interface = Interface::new("bar");
     let mut use_ = Use::new("foo");
-    use_.item("bar", Some("foobar"));
+    use_.item("bar", Some("foobar".into()));
     interface.use_(use_);
     interface.type_def(TypeDef::resource("baz", Vec::<ResourceFunc>::new()));
     package.interface(interface);