[
  {
    "path": ".gitignore",
    "content": "/target\nCargo.lock\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[package]\nname = \"terrors\"\nversion = \"0.3.3\"\nedition = \"2021\"\nauthors = [\"Tyler Neely <tylerneely@gmail.com>\"]\ndocumentation = \"https://docs.rs/terrors/\"\ndescription = \"ergonomic and precise error handling built atop type-level set arithmetic\"\nlicense = \"MIT OR Apache-2.0\"\nrepository = \"https://github.com/komora-io/terrors\"\ncategories = [\"rust-patterns\"]\nkeywords = [\"error\", \"error-handling\", \"type-level\", \"anonymous\", \"sum\"]\nreadme = \"README.md\"\n\n[features]\nerror_provide = []\nerror_provide_feature = []\n"
  },
  {
    "path": "LICENSE-APACHE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2024 Tyler Neely\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "LICENSE-MIT",
    "content": "Copyright (c) 2024 Tyler Neely\n\nPermission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the\nSoftware without restriction, including without\nlimitation the rights to use, copy, modify, merge,\npublish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software\nis furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice\nshall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\nANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\nPARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\nSHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\nIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# terrors - the Rust error **handling** library\n\nHandling errors means taking a set of possible error\ntypes, removing the ones that are locally addressible,\nand then if the set of errors is not within those local\nconcerns, propagating the remainder to a caller. The\ncaller should not receive the local errors of the callee.\n\n# Principles\n\n* Error types should be precise.\n  * `terrors::OneOf` solves this by making precise sets of possible errors:\n    * low friction to specify\n    * low friction to narrow by specific error handlers\n    * low friction to broaden to pass up the stack\n* Error handling should follow the single responsibility principle\n    * if every error in a system is spread everywhere else, there\n      is no clear responsibility for where it needs to be handled.\n* No macros.\n    * Users should not have to learn some new DSL for error handling that every macro entails.\n\n# Examples\n\n```rust\nuse terrors::OneOf;\n\nlet one_of_3: OneOf<(String, u32, Vec<u8>)> = OneOf::new(5);\n\nlet narrowed_res: Result<u32, OneOf<(String, Vec<u8>)>> =\n    one_of_3.narrow();\n\nassert_eq!(5, narrowed_res.unwrap());\n```\n\nOneOf can also be broadened to a superset, checked at compile-time.\n\n```rust\nuse terrors::OneOf;\n\nstruct Timeout;\nstruct AllocationFailure;\nstruct RetriesExhausted;\n\nfn allocate_box() -> Result<Box<u8>, OneOf<(AllocationFailure,)>> {\n    Err(AllocationFailure.into())\n}\n\nfn send() -> Result<(), OneOf<(Timeout,)>> {\n    Err(Timeout.into())\n}\n\nfn allocate_and_send() -> Result<(), OneOf<(AllocationFailure, Timeout)>> {\n    let boxed_byte: Box<u8> = allocate_box().map_err(OneOf::broaden)?;\n    send().map_err(OneOf::broaden)?;\n\n    Ok(())\n}\n\nfn retry() -> Result<(), OneOf<(AllocationFailure, RetriesExhausted)>> {\n    for _ in 0..3 {\n        let Err(err) = allocate_and_send() else {\n            return Ok(());\n        };\n\n        // keep retrying if we have a Timeout,\n        // but punt allocation issues to caller.\n        match err.narrow::<Timeout, _>() {\n            Ok(_timeout) => {},\n            Err(one_of_others) => return Err(one_of_others.broaden()),\n        }\n    }\n\n    Err(OneOf::new(RetriesExhausted))\n}\n```\n\n`OneOf` also implements `Clone`, `Debug`, `Display`, `Send`, `Sync` and/or `std::error::Error` if all types in the type set do as well:\n\n```rust\nuse std::error::Error;\nuse std::io;\nuse terrors::OneOf;\n\nlet o_1: OneOf<(u32, String)> = OneOf::new(5_u32);\n\n// Debug is implemented if all types in the type set implement Debug\ndbg!(&o_1);\n\n// Display is implemented if all types in the type set implement Display\nprintln!(\"{}\", o_1);\n\nlet cloned = o_1.clone();\n\ntype E = io::Error;\nlet e = io::Error::new(io::ErrorKind::Other, \"wuaaaaahhhzzaaaaaaaa\");\n\nlet o_2: OneOf<(E,)> = OneOf::new(e);\n\n// std::error::Error is implemented if all types in the type set implement it\ndbg!(o_2.description());\n```\n\nOneOf can also be turned into an owned or referenced enum form:\n\n```rust\nuse terrors::{OneOf, E2};\n\nlet o_1: OneOf<(u32, String)> = OneOf::new(5_u32);\n\nmatch o_1.as_enum() {\n    E2::A(u) => {\n        println!(\"handling reference {u}: u32\")\n    }\n    E2::B(s) => {\n        println!(\"handling reference {s}: String\")\n    }\n}\n\nmatch o_1.to_enum() {\n    E2::A(u) => {\n        println!(\"handling owned {u}: u32\")\n    }\n    E2::B(s) => {\n        println!(\"handling owned {s}: String\")\n    }\n}\n```\n\n### Motivation\n\nThe paper [Simple Testing Can Prevent Most Critical Failures: An Analysis of Production Failures in Distributed Data-intensive Systems](https://www.eecg.toronto.edu/~yuan/papers/failure_analysis_osdi14.pdf)\nis goldmine of fascinating statistics that illuminate the\nsoftware patterns that tend to correspond to system failures.\nThis is one of my favorites:\n\n```no_compile\nalmost all (92%) of the catastrophic system failures\nare the result of incorrect handling of non-fatal errors\nexplicitly signaled in software.\n```\n\nOur systems are falling over because we aren't handling\nour errors. We're doing fine when it comes to signalling\ntheir existence, but we need to actually handle them.\n\nWhen we write Rust, we tend to encounter a variety of different\nerror types. Sometimes we need to put multiple possible errors\ninto a container that is then returned from a function, where\nthe caller or a transitive caller is expected to handle the\nspecific problem that arose.\n\nAs we grow a codebase, more of these situations pop up.\nWhile it's not so much effort to write custom enums in\none or two places that hold the precise set of possible\nerrors, most people resort to one of two strategies for\nminimizing the effort that goes into propagating their\nerror types:\n* A large top-level enum that holds variants for errors\n  originating across the codebase, tending to grow\n  larger and larger over time, undermining the ability\n  to use exhaustive pattern matching to confidently\n  ensure that local concerns are not bubbling up the stack.\n* A boxed trait that is easy to convert errors into, but\n then hides information about what may actually be inside.\n You don't know where it's been or where it's going.\n\nAs the number of different source error types that these\nerror containers hold increases, the amount of information\nthat the container communicates to people who encounter it\ndecreases. It becomes increasingly unclear what the error\ncontainer actually holds. As the precision of the type\ngoes down, so does a human's ability to reason about\nwhere the appropriate place is to handle any particular\nconcern within it.\n\nWe have to increase the precision in our error types.\n\nPeople don't write a precise enum for every function that\nmay only return some subset of errors because we would\nend up with a ton of small enum types that only get used in\none or two places. This is the pain that drives people\nto using overly-broad error enums or overly-smooth\nboxed dynamic error traits, reducing their ability to\nhandle their errors.\n\n### Cool stuff\n\nThis crate is built around `OneOf`, which functions as\na form of anonymous enum that can be narrowed in ways\nthat may be familiar for users of TypeScript etc...\nOur error containers need to get smaller as individual\nerrors are peeled off and handled, leaving the reduced\nremainder of possible error types if the local concerns\nare not present.\n\nThe cool thing about it is that it is built on top of a\ntype-level heterogenous set of possible error types,\nwhere there's only one actual value among the different\npossibilities.\n\nRather than having a giant ball of mud enum or\nboxed trait object that is never clear what it actually\ncontains, causing you to never handle individual\nconcerns from, the idea of this is that you can\nhave a minimized set of actual error types that may\nthread through the stack.\n\nThe nice thing about this type-level set of possibilities\nis that any specific type can be peeled off while narrowing\nthe rest of the types if the narrowing fails. Both narrowing\nand broadening are based on compile-time error type set checking.\n\n### The Trade-Off\n\nType-level programming is something that I have tried hard to avoid\nfor most of my career due to confusing error messages resulting\nfrom compilation errors. These complex type checking failures\nproduce errors that are challenging to reason about, and can often\ntake several minutes to understand.\n\nI have tried hard to avoid exposing users of `terrors` to too many\nof the sharp edges in the underlying type machinery, but it is likely\nthat if the source and destination type sets do not satisfy the `SupersetOf`\ntrait in the right direction depending on whether `narrow` or\n`broaden` is being called, that the error will not be particularly\npleasant to read. Just know that errors pretty much always mean\nthat the superset relationship does not hold as required.\n\nGoing forward, I believe most of the required traits can be implemented\nin ways that expose users to errors that look more like `(A, B) does not\nimplement SupersetOf<(C, D), _>` instead of `Cons<A, Cons<B, End>> does\nnot implement SupersetOf<Cons<C, Cons<D, End>>>` by leaning into the\nbidirectional type mapping that exists between the heterogenous type\nset `Cons` chains and more human-friendly type tuples.\n\n### Special Thanks\n\nMuch of the fancy type-level logic for reasoning about sets of error types\nwas directly inspired by [frunk](https://docs.rs/frunk/latest/frunk/).\nI had been wondering for years about the feasibility of a data structure\nlike `OneOf`, and had often assumed it was impossible, until I finally\nhad an extended weekend to give it a deep dive. After many false starts,\nI finally came across [an article](https://archive.is/YwDMX) written by\n[lloydmeta](https://github.com/lloydmeta) (the author of frunk) about how\nfrunk handles several related concerns in the context of a heterogenous\nlist structure. Despite having used Rust for over 10 years, that article\ntaught me a huge amount about how the language's type system can be\nused in interesting ways that addressed very practical needs. In particular,\nthe general perspective in that blog post about how you can implement\ntraits in a recursive way that is familiar from other functional languages\nwas the missing primitive for working with Rust that I had not realized\nwas possible for my first decade with the language. Thank you very\nmuch for creating frunk and telling the world about how you did it!\n"
  },
  {
    "path": "src/lib.rs",
    "content": "#![cfg_attr(\n    feature = \"error_provide_feature\",\n    feature(error_generic_member_access)\n)]\n#![doc = include_str!(concat!(env!(\"CARGO_MANIFEST_DIR\"), \"/README.md\"))]\n\n#[doc = include_str!(concat!(env!(\"CARGO_MANIFEST_DIR\"), \"/README.md\"))]\n#[cfg(doctest)]\npub struct ReadmeDoctests;\n\nmod one_of;\nmod one_of_to_enum;\nmod type_set;\n\n/// Similar to anonymous unions / enums in languages that support type narrowing.\npub use one_of::OneOf;\n\npub use type_set::{TypeSet, E1, E2, E3, E4, E5, E6, E7, E8, E9};\n\n/* ------------------------- Helpers ----------------------- */\n\n/// The final element of a type-level Cons list.\n#[doc(hidden)]\n#[derive(Debug)]\npub enum End {}\n\nimpl std::error::Error for End {}\n\n/// A compile-time list of types, similar to other basic functional list structures.\n#[doc(hidden)]\n#[derive(Debug)]\npub struct Cons<Head, Tail>(core::marker::PhantomData<Head>, Tail);\n\n#[doc(hidden)]\n#[derive(Debug)]\npub struct Recurse<Tail>(Tail);\n"
  },
  {
    "path": "src/one_of.rs",
    "content": "use core::any::Any;\nuse core::fmt;\nuse core::marker::PhantomData;\nuse core::ops::Deref;\nuse std::error::Error;\n\nuse crate::type_set::{\n    CloneFold, Contains, DebugFold, DisplayFold, ErrorFold, IsFold, Narrow, SupersetOf, TupleForm,\n    TypeSet,\n};\n\nuse crate::{Cons, End};\n\n/* ------------------------- OneOf ----------------------- */\n\n/// `OneOf` is an open sum type. It differs from an enum\n/// in that you do not need to define any actual new type\n/// in order to hold some specific combination of variants,\n/// but rather you simply describe the OneOf as holding\n/// one value out of several specific possibilities,\n/// defined by using a tuple of those possible variants\n/// as the generic parameter for the `OneOf`.\n///\n/// For example, a `OneOf<(String, u32)>` contains either\n/// a `String` or a `u32`. The value over a simple `Result`\n/// or other traditional enum starts to become apparent in larger\n/// codebases where error handling needs to occur in\n/// different places for different errors. `OneOf` allows\n/// you to quickly specify a function's return value as\n/// involving a precise subset of errors that the caller\n/// can clearly reason about.\npub struct OneOf<E: TypeSet> {\n    pub(crate) value: Box<dyn Any>,\n    _pd: PhantomData<E>,\n}\n\nfn _send_sync_error_assert() {\n    use std::io;\n\n    fn is_send<T: Send>(_: &T) {}\n    fn is_sync<T: Sync>(_: &T) {}\n    fn is_error<T: Error>(_: &T) {}\n\n    let o: OneOf<(io::Error,)> = OneOf::new(io::Error::new(io::ErrorKind::Other, \"yooo\"));\n    is_send(&o);\n    is_sync(&o);\n    is_error(&o);\n}\n\nunsafe impl<T> Send for OneOf<T> where T: TypeSet + Send {}\nunsafe impl<T> Sync for OneOf<T> where T: TypeSet + Sync {}\n\nimpl<T> Deref for OneOf<(T,)>\nwhere\n    T: 'static,\n{\n    type Target = T;\n\n    fn deref(&self) -> &T {\n        self.value.downcast_ref::<T>().unwrap()\n    }\n}\n\nimpl<T> From<T> for OneOf<(T,)>\nwhere\n    T: 'static,\n{\n    fn from(t: T) -> OneOf<(T,)> {\n        OneOf::new(t)\n    }\n}\n\nimpl<E> Clone for OneOf<E>\nwhere\n    E: TypeSet,\n    E::Variants: Clone + CloneFold,\n{\n    fn clone(&self) -> Self {\n        let value = E::Variants::clone_fold(&self.value);\n\n        OneOf {\n            value,\n            _pd: PhantomData,\n        }\n    }\n}\nimpl<E> fmt::Debug for OneOf<E>\nwhere\n    E: TypeSet,\n    E::Variants: fmt::Debug + DebugFold,\n{\n    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n        E::Variants::debug_fold(&self.value, formatter)\n    }\n}\n\nimpl<E> fmt::Display for OneOf<E>\nwhere\n    E: TypeSet,\n    E::Variants: fmt::Display + DisplayFold,\n{\n    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n        E::Variants::display_fold(&self.value, formatter)\n    }\n}\n\nimpl<E> Error for OneOf<E>\nwhere\n    E: TypeSet,\n    E::Variants: Error + DebugFold + DisplayFold + ErrorFold,\n{\n    fn source(&self) -> Option<&(dyn Error + 'static)> {\n        E::Variants::source_fold(&self.value)\n    }\n}\n\nimpl<E> OneOf<E>\nwhere\n    E: TypeSet,\n{\n    /// Create a new `OneOf`.\n    pub fn new<T, Index>(t: T) -> OneOf<E>\n    where\n        T: Any,\n        E::Variants: Contains<T, Index>,\n    {\n        OneOf {\n            value: Box::new(t),\n            _pd: PhantomData,\n        }\n    }\n\n    /// Attempt to downcast the `OneOf` into a specific type, and\n    /// if that fails, return a `OneOf` which does not contain that\n    /// type as one of its possible variants.\n    pub fn narrow<Target, Index>(\n        self,\n    ) -> Result<\n        Target,\n        OneOf<<<E::Variants as Narrow<Target, Index>>::Remainder as TupleForm>::Tuple>,\n    >\n    where\n        Target: 'static,\n        E::Variants: Narrow<Target, Index>,\n    {\n        if self.value.is::<Target>() {\n            Ok(*self.value.downcast::<Target>().unwrap())\n        } else {\n            Err(OneOf {\n                value: self.value,\n                _pd: PhantomData,\n            })\n        }\n    }\n\n    /// Turns the `OneOf` into a `OneOf` with a set of variants\n    /// which is a superset of the current one. This may also be\n    /// the same set of variants, but in a different order.\n    pub fn broaden<Other, Index>(self) -> OneOf<Other>\n    where\n        Other: TypeSet,\n        Other::Variants: SupersetOf<E::Variants, Index>,\n    {\n        OneOf {\n            value: self.value,\n            _pd: PhantomData,\n        }\n    }\n\n    /// Attempt to split a subset of variants out of the `OneOf`,\n    /// returning the remainder of possible variants if the value\n    /// does not have one of the `TargetList` types.\n    pub fn subset<TargetList, Index>(\n        self,\n    ) -> Result<\n        OneOf<TargetList>,\n        OneOf<<<E::Variants as SupersetOf<TargetList::Variants, Index>>::Remainder as TupleForm>::Tuple>,\n    >\n    where\n        TargetList: TypeSet,\n        E::Variants: IsFold + SupersetOf<TargetList::Variants, Index>,\n    {\n        if E::Variants::is_fold(&self.value) {\n            Ok(OneOf {\n                value: self.value,\n                _pd: PhantomData,\n            })\n        } else {\n            Err(OneOf {\n                value: self.value,\n                _pd: PhantomData,\n            })\n        }\n    }\n\n    /// For a `OneOf` with a single variant, return\n    /// the contained value.\n    pub fn take<Target>(self) -> Target\n    where\n        Target: 'static,\n        E: TypeSet<Variants = Cons<Target, End>>,\n    {\n        *self.value.downcast::<Target>().unwrap()\n    }\n\n    /// Convert the `OneOf` to an owned enum for\n    /// use in pattern matching etc...\n    pub fn to_enum(self) -> E::Enum\n    where\n        E::Enum: From<Self>,\n    {\n        E::Enum::from(self)\n    }\n\n    /// Borrow the enum as an enum for use in\n    /// pattern matching etc...\n    pub fn as_enum<'a>(&'a self) -> E::EnumRef<'a>\n    where\n        E::EnumRef<'a>: From<&'a Self>,\n    {\n        E::EnumRef::from(&self)\n    }\n}\n"
  },
  {
    "path": "src/one_of_to_enum.rs",
    "content": "use super::{OneOf, E1, E2, E3, E4, E5, E6, E7, E8, E9};\n\n/* ------------------------- Enum conversions ----------------------- */\n\nimpl<A> From<OneOf<(A,)>> for E1<A>\nwhere\n    A: 'static,\n{\n    fn from(one_of: OneOf<(A,)>) -> Self {\n        E1::A(*one_of.value.downcast().unwrap())\n    }\n}\n\nimpl<'a, A> From<&'a OneOf<(A,)>> for E1<&'a A>\nwhere\n    A: 'static,\n{\n    fn from(one_of: &'a OneOf<(A,)>) -> Self {\n        E1::A(one_of.value.downcast_ref().unwrap())\n    }\n}\n\nimpl<A, B> From<OneOf<(A, B)>> for E2<A, B>\nwhere\n    A: 'static,\n    B: 'static,\n{\n    fn from(one_of: OneOf<(A, B)>) -> Self {\n        if one_of.value.is::<A>() {\n            E2::A(*one_of.value.downcast().unwrap())\n        } else {\n            E2::B(*one_of.value.downcast().unwrap())\n        }\n    }\n}\n\nimpl<'a, A, B> From<&'a OneOf<(A, B)>> for E2<&'a A, &'a B>\nwhere\n    A: 'static,\n    B: 'static,\n{\n    fn from(one_of: &'a OneOf<(A, B)>) -> Self {\n        if one_of.value.is::<A>() {\n            E2::A(one_of.value.downcast_ref().unwrap())\n        } else {\n            E2::B(one_of.value.downcast_ref().unwrap())\n        }\n    }\n}\n\nimpl<A, B, C> From<OneOf<(A, B, C)>> for E3<A, B, C>\nwhere\n    A: 'static,\n    B: 'static,\n    C: 'static,\n{\n    fn from(one_of: OneOf<(A, B, C)>) -> Self {\n        if one_of.value.is::<A>() {\n            E3::A(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<B>() {\n            E3::B(*one_of.value.downcast().unwrap())\n        } else {\n            E3::C(*one_of.value.downcast().unwrap())\n        }\n    }\n}\n\nimpl<'a, A, B, C> From<&'a OneOf<(A, B, C)>> for E3<&'a A, &'a B, &'a C>\nwhere\n    A: 'static,\n    B: 'static,\n    C: 'static,\n{\n    fn from(one_of: &'a OneOf<(A, B, C)>) -> Self {\n        if one_of.value.is::<A>() {\n            E3::A(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<B>() {\n            E3::B(one_of.value.downcast_ref().unwrap())\n        } else {\n            E3::C(one_of.value.downcast_ref().unwrap())\n        }\n    }\n}\n\nimpl<A, B, C, D> From<OneOf<(A, B, C, D)>> for E4<A, B, C, D>\nwhere\n    A: 'static,\n    B: 'static,\n    C: 'static,\n    D: 'static,\n{\n    fn from(one_of: OneOf<(A, B, C, D)>) -> Self {\n        if one_of.value.is::<A>() {\n            E4::A(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<B>() {\n            E4::B(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<C>() {\n            E4::C(*one_of.value.downcast().unwrap())\n        } else {\n            E4::D(*one_of.value.downcast().unwrap())\n        }\n    }\n}\n\nimpl<'a, A, B, C, D> From<&'a OneOf<(A, B, C, D)>> for E4<&'a A, &'a B, &'a C, &'a D>\nwhere\n    A: 'static,\n    B: 'static,\n    C: 'static,\n    D: 'static,\n{\n    fn from(one_of: &'a OneOf<(A, B, C, D)>) -> Self {\n        if one_of.value.is::<A>() {\n            E4::A(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<B>() {\n            E4::B(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<C>() {\n            E4::C(one_of.value.downcast_ref().unwrap())\n        } else {\n            E4::D(one_of.value.downcast_ref().unwrap())\n        }\n    }\n}\n\nimpl<A, B, C, D, E> From<OneOf<(A, B, C, D, E)>> for E5<A, B, C, D, E>\nwhere\n    A: 'static,\n    B: 'static,\n    C: 'static,\n    D: 'static,\n    E: 'static,\n{\n    fn from(one_of: OneOf<(A, B, C, D, E)>) -> Self {\n        if one_of.value.is::<A>() {\n            E5::A(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<B>() {\n            E5::B(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<C>() {\n            E5::C(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<D>() {\n            E5::D(*one_of.value.downcast().unwrap())\n        } else {\n            E5::E(*one_of.value.downcast().unwrap())\n        }\n    }\n}\n\nimpl<'a, A, B, C, D, E> From<&'a OneOf<(A, B, C, D, E)>> for E5<&'a A, &'a B, &'a C, &'a D, &'a E>\nwhere\n    A: 'static,\n    B: 'static,\n    C: 'static,\n    D: 'static,\n    E: 'static,\n{\n    fn from(one_of: &'a OneOf<(A, B, C, D, E)>) -> Self {\n        if one_of.value.is::<A>() {\n            E5::A(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<B>() {\n            E5::B(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<C>() {\n            E5::C(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<D>() {\n            E5::D(one_of.value.downcast_ref().unwrap())\n        } else {\n            E5::E(one_of.value.downcast_ref().unwrap())\n        }\n    }\n}\n\nimpl<A, B, C, D, E, F> From<OneOf<(A, B, C, D, E, F)>> for E6<A, B, C, D, E, F>\nwhere\n    A: 'static,\n    B: 'static,\n    C: 'static,\n    D: 'static,\n    E: 'static,\n    F: 'static,\n{\n    fn from(one_of: OneOf<(A, B, C, D, E, F)>) -> Self {\n        if one_of.value.is::<A>() {\n            E6::A(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<B>() {\n            E6::B(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<C>() {\n            E6::C(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<D>() {\n            E6::D(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<E>() {\n            E6::E(*one_of.value.downcast().unwrap())\n        } else {\n            E6::F(*one_of.value.downcast().unwrap())\n        }\n    }\n}\n\nimpl<'a, A, B, C, D, E, F> From<&'a OneOf<(A, B, C, D, E, F)>>\n    for E6<&'a A, &'a B, &'a C, &'a D, &'a E, &'a F>\nwhere\n    A: 'static,\n    B: 'static,\n    C: 'static,\n    D: 'static,\n    E: 'static,\n    F: 'static,\n{\n    fn from(one_of: &'a OneOf<(A, B, C, D, E, F)>) -> Self {\n        if one_of.value.is::<A>() {\n            E6::A(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<B>() {\n            E6::B(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<C>() {\n            E6::C(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<D>() {\n            E6::D(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<E>() {\n            E6::E(one_of.value.downcast_ref().unwrap())\n        } else {\n            E6::F(one_of.value.downcast_ref().unwrap())\n        }\n    }\n}\n\nimpl<A, B, C, D, E, F, G> From<OneOf<(A, B, C, D, E, F, G)>> for E7<A, B, C, D, E, F, G>\nwhere\n    A: 'static,\n    B: 'static,\n    C: 'static,\n    D: 'static,\n    E: 'static,\n    F: 'static,\n    G: 'static,\n{\n    fn from(one_of: OneOf<(A, B, C, D, E, F, G)>) -> Self {\n        if one_of.value.is::<A>() {\n            E7::A(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<B>() {\n            E7::B(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<C>() {\n            E7::C(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<D>() {\n            E7::D(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<E>() {\n            E7::E(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<F>() {\n            E7::F(*one_of.value.downcast().unwrap())\n        } else {\n            E7::G(*one_of.value.downcast().unwrap())\n        }\n    }\n}\n\nimpl<'a, A, B, C, D, E, F, G> From<&'a OneOf<(A, B, C, D, E, F, G)>>\n    for E7<&'a A, &'a B, &'a C, &'a D, &'a E, &'a F, &'a G>\nwhere\n    A: 'static,\n    B: 'static,\n    C: 'static,\n    D: 'static,\n    E: 'static,\n    F: 'static,\n    G: 'static,\n{\n    fn from(one_of: &'a OneOf<(A, B, C, D, E, F, G)>) -> Self {\n        if one_of.value.is::<A>() {\n            E7::A(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<B>() {\n            E7::B(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<C>() {\n            E7::C(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<D>() {\n            E7::D(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<E>() {\n            E7::E(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<F>() {\n            E7::F(one_of.value.downcast_ref().unwrap())\n        } else {\n            E7::G(one_of.value.downcast_ref().unwrap())\n        }\n    }\n}\n\nimpl<A, B, C, D, E, F, G, H> From<OneOf<(A, B, C, D, E, F, G, H)>> for E8<A, B, C, D, E, F, G, H>\nwhere\n    A: 'static,\n    B: 'static,\n    C: 'static,\n    D: 'static,\n    E: 'static,\n    F: 'static,\n    G: 'static,\n    H: 'static,\n{\n    fn from(one_of: OneOf<(A, B, C, D, E, F, G, H)>) -> Self {\n        if one_of.value.is::<A>() {\n            E8::A(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<B>() {\n            E8::B(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<C>() {\n            E8::C(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<D>() {\n            E8::D(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<E>() {\n            E8::E(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<F>() {\n            E8::F(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<G>() {\n            E8::G(*one_of.value.downcast().unwrap())\n        } else {\n            E8::H(*one_of.value.downcast().unwrap())\n        }\n    }\n}\n\nimpl<'a, A, B, C, D, E, F, G, H> From<&'a OneOf<(A, B, C, D, E, F, G, H)>>\n    for E8<&'a A, &'a B, &'a C, &'a D, &'a E, &'a F, &'a G, &'a H>\nwhere\n    A: 'static,\n    B: 'static,\n    C: 'static,\n    D: 'static,\n    E: 'static,\n    F: 'static,\n    G: 'static,\n    H: 'static,\n{\n    fn from(one_of: &'a OneOf<(A, B, C, D, E, F, G, H)>) -> Self {\n        if one_of.value.is::<A>() {\n            E8::A(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<B>() {\n            E8::B(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<C>() {\n            E8::C(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<D>() {\n            E8::D(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<E>() {\n            E8::E(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<F>() {\n            E8::F(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<G>() {\n            E8::G(one_of.value.downcast_ref().unwrap())\n        } else {\n            E8::H(one_of.value.downcast_ref().unwrap())\n        }\n    }\n}\n\nimpl<A, B, C, D, E, F, G, H, I> From<OneOf<(A, B, C, D, E, F, G, H, I)>>\n    for E9<A, B, C, D, E, F, G, H, I>\nwhere\n    A: 'static,\n    B: 'static,\n    C: 'static,\n    D: 'static,\n    E: 'static,\n    F: 'static,\n    G: 'static,\n    H: 'static,\n    I: 'static,\n{\n    fn from(one_of: OneOf<(A, B, C, D, E, F, G, H, I)>) -> Self {\n        if one_of.value.is::<A>() {\n            E9::A(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<B>() {\n            E9::B(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<C>() {\n            E9::C(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<D>() {\n            E9::D(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<E>() {\n            E9::E(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<F>() {\n            E9::F(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<G>() {\n            E9::G(*one_of.value.downcast().unwrap())\n        } else if one_of.value.is::<H>() {\n            E9::H(*one_of.value.downcast().unwrap())\n        } else {\n            E9::I(*one_of.value.downcast().unwrap())\n        }\n    }\n}\n\nimpl<'a, A, B, C, D, E, F, G, H, I> From<&'a OneOf<(A, B, C, D, E, F, G, H, I)>>\n    for E9<&'a A, &'a B, &'a C, &'a D, &'a E, &'a F, &'a G, &'a H, &'a I>\nwhere\n    A: 'static,\n    B: 'static,\n    C: 'static,\n    D: 'static,\n    E: 'static,\n    F: 'static,\n    G: 'static,\n    H: 'static,\n    I: 'static,\n{\n    fn from(one_of: &'a OneOf<(A, B, C, D, E, F, G, H, I)>) -> Self {\n        if one_of.value.is::<A>() {\n            E9::A(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<B>() {\n            E9::B(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<C>() {\n            E9::C(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<D>() {\n            E9::D(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<E>() {\n            E9::E(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<F>() {\n            E9::F(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<G>() {\n            E9::G(one_of.value.downcast_ref().unwrap())\n        } else if one_of.value.is::<H>() {\n            E9::H(one_of.value.downcast_ref().unwrap())\n        } else {\n            E9::I(one_of.value.downcast_ref().unwrap())\n        }\n    }\n}\n"
  },
  {
    "path": "src/type_set.rs",
    "content": "//! Type-level set inclusion and difference, inspired by frunk's approach: <https://archive.is/YwDMX>\nuse core::any::Any;\nuse core::fmt;\nuse std::error::Error;\n\nuse crate::{Cons, End, Recurse};\n\n/* ------------------------- std::error::Error support ----------------------- */\n\npub trait ErrorFold {\n    fn source_fold(any: &Box<dyn Any>) -> Option<&(dyn Error + 'static)>;\n\n    #[cfg(feature = \"error_provide\")]\n    fn provide_fold<'a>(any: &'a Box<dyn Any>, request: &mut std::error::Request<'a>);\n}\n\nimpl ErrorFold for End {\n    fn source_fold(_: &Box<dyn Any>) -> Option<&(dyn Error + 'static)> {\n        unreachable!(\"source_fold called on End\");\n    }\n\n    #[cfg(feature = \"error_provide\")]\n    fn provide_fold<'a>(_: &Box<dyn Any>, _: &mut std::error::Request<'a>) {\n        unreachable!(\"provide_fold called on End\");\n    }\n}\n\nimpl<Head, Tail> Error for Cons<Head, Tail>\nwhere\n    Head: Error,\n    Tail: Error,\n{\n}\n\nimpl<Head, Tail> ErrorFold for Cons<Head, Tail>\nwhere\n    Cons<Head, Tail>: Error,\n    Head: 'static + Error,\n    Tail: ErrorFold,\n{\n    fn source_fold(any: &Box<dyn Any>) -> Option<&(dyn Error + 'static)> {\n        if let Some(head_ref) = any.downcast_ref::<Head>() {\n            head_ref.source()\n        } else {\n            Tail::source_fold(any)\n        }\n    }\n\n    #[cfg(feature = \"error_provide\")]\n    fn provide_fold<'a>(any: &'a Box<dyn Any>, request: &mut std::error::Request<'a>) {\n        if let Some(head_ref) = any.downcast_ref::<Head>() {\n            head_ref.provide(request)\n        } else {\n            Tail::provide_fold(any, request)\n        }\n    }\n}\n\n/* ------------------------- Display support ----------------------- */\n\nimpl<Head, Tail> fmt::Display for Cons<Head, Tail>\nwhere\n    Head: fmt::Display,\n    Tail: fmt::Display,\n{\n    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {\n        unreachable!(\"Display called for Cons which is not constructable\")\n    }\n}\n\nimpl fmt::Display for End {\n    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {\n        unreachable!(\"Display::fmt called for an End, which is not constructible.\")\n    }\n}\n\npub trait DisplayFold {\n    fn display_fold(any: &Box<dyn Any>, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;\n}\n\nimpl DisplayFold for End {\n    fn display_fold(_: &Box<dyn Any>, _: &mut fmt::Formatter<'_>) -> fmt::Result {\n        unreachable!(\"display_fold called on End\");\n    }\n}\n\nimpl<Head, Tail> DisplayFold for Cons<Head, Tail>\nwhere\n    Cons<Head, Tail>: fmt::Display,\n    Head: 'static + fmt::Display,\n    Tail: DisplayFold,\n{\n    fn display_fold(any: &Box<dyn Any>, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n        if let Some(head_ref) = any.downcast_ref::<Head>() {\n            head_ref.fmt(formatter)\n        } else {\n            Tail::display_fold(any, formatter)\n        }\n    }\n}\n\n/* ------------------------- Debug support ----------------------- */\n\npub trait DebugFold {\n    fn debug_fold(any: &Box<dyn Any>, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;\n}\n\nimpl DebugFold for End {\n    fn debug_fold(_: &Box<dyn Any>, _: &mut fmt::Formatter<'_>) -> fmt::Result {\n        unreachable!(\"debug_fold called on End\");\n    }\n}\n\nimpl<Head, Tail> DebugFold for Cons<Head, Tail>\nwhere\n    Cons<Head, Tail>: fmt::Debug,\n    Head: 'static + fmt::Debug,\n    Tail: DebugFold,\n{\n    fn debug_fold(any: &Box<dyn Any>, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n        if let Some(head_ref) = any.downcast_ref::<Head>() {\n            head_ref.fmt(formatter)\n        } else {\n            Tail::debug_fold(any, formatter)\n        }\n    }\n}\n\n/* ------------------------- Clone support ----------------------- */\n\npub trait CloneFold {\n    fn clone_fold(any: &Box<dyn Any>) -> Box<dyn Any>;\n}\n\nimpl Clone for End {\n    fn clone(&self) -> End {\n        unreachable!(\"clone called for End\");\n    }\n}\n\nimpl<Head, Tail> Clone for Cons<Head, Tail>\nwhere\n    Head: 'static + Clone,\n    Tail: CloneFold,\n{\n    fn clone(&self) -> Self {\n        unreachable!(\"clone called for Cons which is not constructable\");\n    }\n}\n\nimpl CloneFold for End {\n    fn clone_fold(_: &Box<dyn Any>) -> Box<dyn Any> {\n        unreachable!(\"clone_fold called on End\");\n    }\n}\n\nimpl<Head, Tail> CloneFold for Cons<Head, Tail>\nwhere\n    Head: 'static + Clone,\n    Tail: CloneFold,\n{\n    fn clone_fold(any: &Box<dyn Any>) -> Box<dyn Any> {\n        if let Some(head_ref) = any.downcast_ref::<Head>() {\n            Box::new(head_ref.clone())\n        } else {\n            Tail::clone_fold(any)\n        }\n    }\n}\n\nfn _clone_test() {\n    fn is_clone<T: Clone>() {}\n\n    type T0 = <(String, u32) as TypeSet>::Variants;\n\n    is_clone::<T0>();\n}\n\n/* ------------------------- Any::is support ----------------------- */\n\npub trait IsFold {\n    fn is_fold(any: &Box<dyn Any>) -> bool;\n}\n\nimpl IsFold for End {\n    fn is_fold(_: &Box<dyn Any>) -> bool {\n        false\n    }\n}\n\nimpl<Head, Tail> IsFold for Cons<Head, Tail>\nwhere\n    Head: 'static,\n    Tail: IsFold,\n{\n    fn is_fold(any: &Box<dyn Any>) -> bool {\n        if any.is::<Head>() {\n            true\n        } else {\n            Tail::is_fold(any)\n        }\n    }\n}\n\n/* ------------------------- TypeSet implemented for tuples ----------------------- */\n\npub trait TypeSet {\n    type Variants: TupleForm;\n    type Enum;\n    type EnumRef<'a>\n    where\n        Self: 'a;\n}\n\nimpl TypeSet for () {\n    type Variants = End;\n    type Enum = E0;\n    type EnumRef<'a> = E0 where Self: 'a;\n}\n\nimpl<A> TypeSet for (A,) {\n    type Variants = Cons<A, End>;\n    type Enum = E1<A>;\n    type EnumRef<'a> = E1<&'a A> where Self: 'a;\n}\n\nimpl<A, B> TypeSet for (A, B) {\n    type Variants = Cons<A, Cons<B, End>>;\n    type Enum = E2<A, B>;\n    type EnumRef<'a> = E2<&'a A, &'a B> where Self: 'a;\n}\n\nimpl<A, B, C> TypeSet for (A, B, C) {\n    type Variants = Cons<A, Cons<B, Cons<C, End>>>;\n    type Enum = E3<A, B, C>;\n    type EnumRef<'a> = E3<&'a A, &'a B, &'a C> where Self: 'a;\n}\n\nimpl<A, B, C, D> TypeSet for (A, B, C, D) {\n    type Variants = Cons<A, Cons<B, Cons<C, Cons<D, End>>>>;\n    type Enum = E4<A, B, C, D>;\n    type EnumRef<'a> = E4<&'a A, &'a B, &'a C, &'a D> where Self: 'a;\n}\n\nimpl<A, B, C, D, E> TypeSet for (A, B, C, D, E) {\n    type Variants = Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, End>>>>>;\n    type Enum = E5<A, B, C, D, E>;\n    type EnumRef<'a> = E5<&'a A, &'a B, &'a C, &'a D, &'a E> where Self: 'a;\n}\n\nimpl<A, B, C, D, E, F> TypeSet for (A, B, C, D, E, F) {\n    type Variants = Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, End>>>>>>;\n    type Enum = E6<A, B, C, D, E, F>;\n    type EnumRef<'a> = E6<&'a A, &'a B, &'a C, &'a D, &'a E, &'a F> where Self: 'a;\n}\n\nimpl<A, B, C, D, E, F, G> TypeSet for (A, B, C, D, E, F, G) {\n    type Variants = Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, Cons<G, End>>>>>>>;\n    type Enum = E7<A, B, C, D, E, F, G>;\n    type EnumRef<'a> = E7<&'a A, &'a B, &'a C, &'a D, &'a E, &'a F, &'a G> where Self: 'a;\n}\n\nimpl<A, B, C, D, E, F, G, H> TypeSet for (A, B, C, D, E, F, G, H) {\n    type Variants = Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, Cons<G, Cons<H, End>>>>>>>>;\n    type Enum = E8<A, B, C, D, E, F, G, H>;\n    type EnumRef<'a> = E8<&'a A, &'a B, &'a C, &'a D, &'a E, &'a F, &'a G, &'a H> where Self: 'a;\n}\n\nimpl<A, B, C, D, E, F, G, H, I> TypeSet for (A, B, C, D, E, F, G, H, I) {\n    type Variants =\n        Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, Cons<G, Cons<H, Cons<I, End>>>>>>>>>;\n    type Enum = E9<A, B, C, D, E, F, G, H, I>;\n    type EnumRef<'a> = E9<&'a A, &'a B, &'a C, &'a D, &'a E, &'a F, &'a G, &'a H, &'a I> where Self: 'a;\n}\n\n/* ------------------------- TupleForm implemented for TypeSet ----------------------- */\n\npub trait TupleForm {\n    type Tuple: TypeSet;\n}\n\nimpl TupleForm for End {\n    type Tuple = ();\n}\n\nimpl<A> TupleForm for Cons<A, End> {\n    type Tuple = (A,);\n}\n\nimpl<A, B> TupleForm for Cons<A, Cons<B, End>> {\n    type Tuple = (A, B);\n}\n\nimpl<A, B, C> TupleForm for Cons<A, Cons<B, Cons<C, End>>> {\n    type Tuple = (A, B, C);\n}\n\nimpl<A, B, C, D> TupleForm for Cons<A, Cons<B, Cons<C, Cons<D, End>>>> {\n    type Tuple = (A, B, C, D);\n}\n\nimpl<A, B, C, D, E> TupleForm for Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, End>>>>> {\n    type Tuple = (A, B, C, D, E);\n}\n\nimpl<A, B, C, D, E, F> TupleForm for Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, End>>>>>> {\n    type Tuple = (A, B, C, D, E, F);\n}\n\nimpl<A, B, C, D, E, F, G> TupleForm\n    for Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, Cons<G, End>>>>>>>\n{\n    type Tuple = (A, B, C, D, E, F, G);\n}\n\nimpl<A, B, C, D, E, F, G, H> TupleForm\n    for Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, Cons<G, Cons<H, End>>>>>>>>\n{\n    type Tuple = (A, B, C, D, E, F, G, H);\n}\n\nimpl<A, B, C, D, E, F, G, H, I> TupleForm\n    for Cons<A, Cons<B, Cons<C, Cons<D, Cons<E, Cons<F, Cons<G, Cons<H, Cons<I, End>>>>>>>>>\n{\n    type Tuple = (A, B, C, D, E, F, G, H, I);\n}\n\n/* ------------------------- Lifted ----------------------- */\n\npub enum E0 {}\npub enum E1<A> {\n    A(A),\n}\nimpl<A> From<A> for E1<A> {\n    fn from(a: A) -> E1<A> {\n        E1::A(a)\n    }\n}\npub enum E2<A, B> {\n    A(A),\n    B(B),\n}\npub enum E3<A, B, C> {\n    A(A),\n    B(B),\n    C(C),\n}\npub enum E4<A, B, C, D> {\n    A(A),\n    B(B),\n    C(C),\n    D(D),\n}\npub enum E5<A, B, C, D, E> {\n    A(A),\n    B(B),\n    C(C),\n    D(D),\n    E(E),\n}\npub enum E6<A, B, C, D, E, F> {\n    A(A),\n    B(B),\n    C(C),\n    D(D),\n    E(E),\n    F(F),\n}\npub enum E7<A, B, C, D, E, F, G> {\n    A(A),\n    B(B),\n    C(C),\n    D(D),\n    E(E),\n    F(F),\n    G(G),\n}\npub enum E8<A, B, C, D, E, F, G, H> {\n    A(A),\n    B(B),\n    C(C),\n    D(D),\n    E(E),\n    F(F),\n    G(G),\n    H(H),\n}\npub enum E9<A, B, C, D, E, F, G, H, I> {\n    A(A),\n    B(B),\n    C(C),\n    D(D),\n    E(E),\n    F(F),\n    G(G),\n    H(H),\n    I(I),\n}\n\n/* ------------------------- Contains ----------------------- */\n\n/// A trait that assists with compile-time type set inclusion testing.\n/// The `Index` parameter is either `End` or `Cons<...>` depending on\n/// whether the trait implementation is a base case or the recursive\n/// case.\npub trait Contains<T, Index> {}\n\n/// Base case implementation for when the Cons Head is T.\nimpl<T, Tail> Contains<T, End> for Cons<T, Tail> {}\n\n/// Recursive case for when the Cons Tail contains T.\nimpl<T, Index, Head, Tail> Contains<T, Cons<Index, ()>> for Cons<Head, Tail> where\n    Tail: Contains<T, Index>\n{\n}\n\n/* ------------------------- Narrow ----------------------- */\n\n/// A trait for pulling a specific type out of a Variants at compile-time\n/// and having access to the other types as the Remainder.\npub trait Narrow<Target, Index>: TupleForm {\n    type Remainder: TupleForm;\n}\n\n/// Base case where the search Target is in the Head of the Variants.\nimpl<Target, Tail> Narrow<Target, End> for Cons<Target, Tail>\nwhere\n    Tail: TupleForm,\n    Cons<Target, Tail>: TupleForm,\n{\n    type Remainder = Tail;\n}\n\n/// Recursive case where the search Target is in the Tail of the Variants.\nimpl<Head, Tail, Target, Index> Narrow<Target, Recurse<Index>> for Cons<Head, Tail>\nwhere\n    Tail: Narrow<Target, Index>,\n    Tail: TupleForm,\n    Cons<Head, Tail>: TupleForm,\n    Cons<Head, <Tail as Narrow<Target, Index>>::Remainder>: TupleForm,\n{\n    type Remainder = Cons<Head, <Tail as Narrow<Target, Index>>::Remainder>;\n}\n\nfn _narrow_test() {\n    fn can_narrow<Types, Target, Remainder, Index>()\n    where\n        Types: Narrow<Target, Index, Remainder = Remainder>,\n    {\n    }\n\n    type T0 = <(u32, String) as TypeSet>::Variants;\n\n    can_narrow::<T0, u32, _, _>();\n    can_narrow::<T0, String, Cons<u32, End>, _>();\n}\n\n/* ------------------------- SupersetOf ----------------------- */\n\n/// When all types in a Variants are present in a second Variants\npub trait SupersetOf<Other, Index> {\n    type Remainder: TupleForm;\n}\n\n/// Base case\nimpl<T: TupleForm> SupersetOf<End, End> for T {\n    type Remainder = T;\n}\n\n/// Recursive case - more complex because we have to reason about the Index itself as a\n/// heterogenous list.\nimpl<SubHead, SubTail, SuperHead, SuperTail, HeadIndex, TailIndex>\n    SupersetOf<Cons<SubHead, SubTail>, Cons<HeadIndex, TailIndex>> for Cons<SuperHead, SuperTail>\nwhere\n    Cons<SuperHead, SuperTail>: Narrow<SubHead, HeadIndex>,\n    <Cons<SuperHead, SuperTail> as Narrow<SubHead, HeadIndex>>::Remainder:\n        SupersetOf<SubTail, TailIndex>,\n{\n    type Remainder =\n        <<Cons<SuperHead, SuperTail> as Narrow<SubHead, HeadIndex>>::Remainder as SupersetOf<\n            SubTail,\n            TailIndex,\n        >>::Remainder;\n}\n\nfn _superset_test() {\n    fn is_superset<S1, S2, Remainder, Index>()\n    where\n        S1: SupersetOf<S2, Index, Remainder = Remainder>,\n    {\n    }\n\n    type T0 = <(u32,) as TypeSet>::Variants;\n    type T1A = <(u32, String) as TypeSet>::Variants;\n    type T1B = <(String, u32) as TypeSet>::Variants;\n    type T2 = <(String, i32, u32) as TypeSet>::Variants;\n    type T3 = <(Vec<u8>, Vec<i8>, u32, f32, String, f64, i32) as TypeSet>::Variants;\n\n    is_superset::<T0, T0, _, _>();\n    is_superset::<T1A, T1A, _, _>();\n    is_superset::<T1A, T1B, _, _>();\n    is_superset::<T1B, T1A, _, _>();\n    is_superset::<T2, T2, _, _>();\n    is_superset::<T1A, T0, _, _>();\n    is_superset::<T1B, T0, _, _>();\n    is_superset::<T2, T0, <(String, i32) as TypeSet>::Variants, _>();\n    is_superset::<T2, T1A, <(i32,) as TypeSet>::Variants, _>();\n    is_superset::<T2, T1B, <(i32,) as TypeSet>::Variants, _>();\n    is_superset::<T3, T1A, <(Vec<u8>, Vec<i8>, f32, f64, i32) as TypeSet>::Variants, _>();\n    is_superset::<T3, T1B, _, _>();\n    is_superset::<T3, T0, _, _>();\n    is_superset::<T3, T2, _, _>();\n\n    type T5sup = <(u8, u16, u32, u64, u128) as TypeSet>::Variants;\n    type T5sub = <(u8, u128) as TypeSet>::Variants;\n    type T5rem = <(u16, u32, u64) as TypeSet>::Variants;\n\n    is_superset::<T5sup, T5sub, T5rem, _>();\n}\n"
  },
  {
    "path": "tests/usability.rs",
    "content": "use terrors::OneOf;\n\n#[derive(Debug)]\nstruct NotEnoughMemory;\n\n#[derive(Debug)]\nstruct Timeout;\n\n#[derive(Debug)]\nstruct RetriesExhausted;\n\n#[test]\nfn retry() {\n    fn inner() -> Result<(), OneOf<(NotEnoughMemory, RetriesExhausted)>> {\n        for _ in 0..3 {\n            let Err(err) = does_stuff() else {\n                return Ok(());\n            };\n\n            match err.narrow::<Timeout, _>() {\n                Ok(_timeout) => continue,\n                Err(allocation_oneof) => {\n                    println!(\"didn't get Timeout, now trying to get NotEnoughMemory\");\n                    let allocation_oneof: OneOf<(NotEnoughMemory,)> = allocation_oneof;\n                    let allocation = allocation_oneof.narrow::<NotEnoughMemory, _>().unwrap();\n\n                    return Err(OneOf::new(allocation));\n                }\n            }\n        }\n\n        Err(OneOf::new(RetriesExhausted))\n    }\n\n    let _ = dbg!(inner());\n}\n\nfn does_stuff() -> Result<(), OneOf<(NotEnoughMemory, Timeout)>> {\n    // TODO Try impl after superset type work\n    let _allocation = match allocates() {\n        Ok(a) => a,\n        Err(e) => return Err(e.broaden()),\n    };\n\n    // TODO Try impl after superset type work\n    let _chat = match chats() {\n        Ok(c) => c,\n        Err(e) => return Err(OneOf::new(e)),\n    };\n\n    Ok(())\n}\n\nfn allocates() -> Result<(), OneOf<(NotEnoughMemory,)>> {\n    let result: Result<(), NotEnoughMemory> = Err(NotEnoughMemory);\n\n    result?;\n\n    Ok(())\n}\n\nfn chats() -> Result<(), Timeout> {\n    Err(Timeout)\n}\n\n#[test]\nfn smoke() {\n    let o_1: OneOf<(u32, String)> = OneOf::new(5_u32);\n    let _narrowed_1: u32 = o_1.narrow::<u32, _>().unwrap();\n\n    let o_2: OneOf<(String, u32)> = OneOf::new(5_u32);\n    let _narrowed_2: u32 = o_2.narrow::<u32, _>().unwrap();\n\n    let o_3: OneOf<(String, u32)> = OneOf::new(\"5\".to_string());\n    let _narrowed_3: OneOf<(String,)> = o_3.narrow::<u32, _>().unwrap_err();\n\n    let o_4: OneOf<(String, u32)> = OneOf::new(\"5\".to_string());\n\n    let _: String = o_4.narrow().unwrap();\n\n    let o_5: OneOf<(String, u32)> = OneOf::new(\"5\".to_string());\n    o_5.narrow::<String, _>().unwrap();\n\n    let o_6: OneOf<(String, u32)> = OneOf::new(\"5\".to_string());\n    let o_7: OneOf<(u32, String)> = o_6.broaden();\n    let o_8: OneOf<(String, u32)> = o_7.subset().unwrap();\n    let _: OneOf<(u32, String)> = o_8.subset().unwrap();\n\n    let o_9: OneOf<(u8, u16, u32)> = OneOf::new(3_u32);\n    let _: Result<OneOf<(u16,)>, OneOf<(u8, u32)>> = o_9.subset();\n    let o_10: OneOf<(u8, u16, u32)> = OneOf::new(3_u32);\n    let _: Result<u16, OneOf<(u8, u32)>> = o_10.narrow();\n}\n\n#[test]\nfn debug() {\n    use std::error::Error;\n    use std::io;\n\n    let o_1: OneOf<(u32, String)> = OneOf::new(5_u32);\n\n    // Debug is implemented if all types in the type set implement Debug\n    dbg!(&o_1);\n\n    // Display is implemented if all types in the type set implement Display\n    println!(\"{}\", o_1);\n\n    type E = io::Error;\n    let e = io::Error::new(io::ErrorKind::Other, \"wuaaaaahhhzzaaaaaaaa\");\n\n    let o_2: OneOf<(E,)> = OneOf::new(e);\n\n    // std::error::Error is implemented if all types in the type set implement it\n    dbg!(o_2.source());\n\n    let o_3: OneOf<(u32, String)> = OneOf::new(\"hey\".to_string());\n    dbg!(o_3);\n}\n\n#[test]\nfn multi_match() {\n    use terrors::E2;\n\n    let o_1: OneOf<(u32, String)> = OneOf::new(5_u32);\n\n    match o_1.as_enum() {\n        E2::A(u) => {\n            println!(\"handling {u}: u32\")\n        }\n        E2::B(s) => {\n            println!(\"handling {s}: String\")\n        }\n    }\n\n    match o_1.to_enum() {\n        E2::A(u) => {\n            println!(\"handling {u}: u32\")\n        }\n        E2::B(s) => {\n            println!(\"handling {s}: String\")\n        }\n    }\n}\n\n#[test]\nfn multi_narrow() {\n    use terrors::E2;\n\n    struct Timeout {}\n    struct Backoff {}\n\n    let o_1: OneOf<(u8, u16, u32, u64, u128)> = OneOf::new(5_u32);\n\n    let _narrow_res: Result<OneOf<(u8, u128)>, OneOf<(u16, u32, u64)>> = o_1.subset();\n\n    let o_2: OneOf<(u8, u16, Backoff, Timeout, u32, u64, u128)> = OneOf::new(Timeout {});\n\n    match o_2.subset::<(Timeout, Backoff), _>().unwrap().to_enum() {\n        E2::A(Timeout {}) => {\n            println!(\":)\");\n        }\n        E2::B(Backoff {}) => {\n            unreachable!()\n        }\n    }\n}\n"
  }
]