129 lines
13 KiB
HTML
129 lines
13 KiB
HTML
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Build status Latest version Documentation"><title>downcast_rs - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../static.files/rustdoc-42caa33d.css"><meta name="rustdoc-vars" data-root-path="../" data-static-root-path="../static.files/" data-current-crate="downcast_rs" data-themes="" data-resource-suffix="" data-rustdoc-version="1.84.0 (9fc6b4312 2025-01-07)" data-channel="1.84.0" data-search-js="search-92e6798f.js" data-settings-js="settings-0f613d39.js" ><script src="../static.files/storage-59e33391.js"></script><script defer src="../crates.js"></script><script defer src="../static.files/main-5f194d8c.js"></script><noscript><link rel="stylesheet" href="../static.files/noscript-893ab5e7.css"></noscript><link rel="alternate icon" type="image/png" href="../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../static.files/favicon-044be391.svg"></head><body class="rustdoc mod crate"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../downcast_rs/index.html">downcast_<wbr>rs</a><span class="version">1.2.1</span></h2></div><div class="sidebar-elems"><ul class="block"><li><a id="all-types" href="all.html">All Items</a></li></ul><section id="rustdoc-toc"><h3><a href="#">Sections</a></h3><ul class="block top-toc"><li><a href="#usage" title="Usage">Usage</a></li><li><a href="#example-without-generics" title="Example without generics">Example without generics</a></li><li><a href="#example-with-a-generic-trait-with-associated-types-and-constraints" title="Example with a generic trait with associated types and constraints">Example with a generic trait with associated types and constraints</a></li></ul><h3><a href="#macros">Crate Items</a></h3><ul class="block"><li><a href="#macros" title="Macros">Macros</a></li><li><a href="#traits" title="Traits">Traits</a></li></ul></section><div id="rustdoc-modnav"></div></div></nav><div class="sidebar-resizer"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><h1>Crate <span>downcast_rs</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../src/downcast_rs/lib.rs.html#1-690">Source</a> </span></div><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p><a href="https://github.com/marcianx/downcast-rs/actions"><img src="https://img.shields.io/github/actions/workflow/status/marcianx/downcast-rs/main.yml?branch=master" alt="Build status" /></a>
|
|
<a href="https://crates.io/crates/downcast-rs"><img src="https://img.shields.io/crates/v/downcast-rs.svg" alt="Latest version" /></a>
|
|
<a href="https://docs.rs/downcast-rs"><img src="https://docs.rs/downcast-rs/badge.svg" alt="Documentation" /></a></p>
|
|
<p>Rust enums are great for types where all variations are known beforehand. But a
|
|
container of user-defined types requires an open-ended type like a <strong>trait
|
|
object</strong>. Some applications may want to cast these trait objects back to the
|
|
original concrete types to access additional functionality and performant
|
|
inlined implementations.</p>
|
|
<p><code>downcast-rs</code> adds this downcasting support to trait objects using only safe
|
|
Rust. It supports <strong>type parameters</strong>, <strong>associated types</strong>, and <strong>constraints</strong>.</p>
|
|
<h2 id="usage"><a class="doc-anchor" href="#usage">§</a>Usage</h2>
|
|
<p>Add the following to your <code>Cargo.toml</code>:</p>
|
|
<div class="example-wrap"><pre class="language-toml"><code>[dependencies]
|
|
downcast-rs = "1.2.1"</code></pre></div>
|
|
<p>This crate is <code>no_std</code> compatible. To use it without <code>std</code>:</p>
|
|
<div class="example-wrap"><pre class="language-toml"><code>[dependencies]
|
|
downcast-rs = { version = "1.2.0", default-features = false }</code></pre></div>
|
|
<p>To make a trait downcastable, make it extend either <code>downcast::Downcast</code> or
|
|
<code>downcast::DowncastSync</code> and invoke <code>impl_downcast!</code> on it as in the examples
|
|
below.</p>
|
|
<p>Since 1.2.0, the minimum supported Rust version is 1.36 due to needing stable access to alloc.</p>
|
|
|
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">trait </span>Trait: Downcast {}
|
|
<span class="macro">impl_downcast!</span>(Trait);
|
|
|
|
<span class="comment">// Also supports downcasting `Arc`-ed trait objects by extending `DowncastSync`
|
|
// and starting `impl_downcast!` with `sync`.
|
|
</span><span class="kw">trait </span>TraitSync: DowncastSync {}
|
|
<span class="macro">impl_downcast!</span>(sync TraitSync);
|
|
|
|
<span class="comment">// With type parameters.
|
|
</span><span class="kw">trait </span>TraitGeneric1<T>: Downcast {}
|
|
<span class="macro">impl_downcast!</span>(TraitGeneric1<T>);
|
|
|
|
<span class="comment">// With associated types.
|
|
</span><span class="kw">trait </span>TraitGeneric2: Downcast { <span class="kw">type </span>G; <span class="kw">type </span>H; }
|
|
<span class="macro">impl_downcast!</span>(TraitGeneric2 assoc G, H);
|
|
|
|
<span class="comment">// With constraints on types.
|
|
</span><span class="kw">trait </span>TraitGeneric3<T: Copy>: Downcast {
|
|
<span class="kw">type </span>H: Clone;
|
|
}
|
|
<span class="macro">impl_downcast!</span>(TraitGeneric3<T> assoc H <span class="kw">where </span>T: Copy, H: Clone);
|
|
|
|
<span class="comment">// With concrete types.
|
|
</span><span class="kw">trait </span>TraitConcrete1<T: Copy>: Downcast {}
|
|
<span class="macro">impl_downcast!</span>(concrete TraitConcrete1<u32>);
|
|
|
|
<span class="kw">trait </span>TraitConcrete2<T: Copy>: Downcast { <span class="kw">type </span>H; }
|
|
<span class="macro">impl_downcast!</span>(concrete TraitConcrete2<u32> assoc H=f64);</code></pre></div>
|
|
<h2 id="example-without-generics"><a class="doc-anchor" href="#example-without-generics">§</a>Example without generics</h2>
|
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="comment">// Import macro via `macro_use` pre-1.30.
|
|
</span><span class="attr">#[macro_use]
|
|
</span><span class="kw">extern crate </span>downcast_rs;
|
|
<span class="kw">use </span>downcast_rs::DowncastSync;
|
|
|
|
<span class="comment">// To create a trait with downcasting methods, extend `Downcast` or `DowncastSync`
|
|
// and run `impl_downcast!()` on the trait.
|
|
</span><span class="kw">trait </span>Base: DowncastSync {}
|
|
<span class="macro">impl_downcast!</span>(sync Base); <span class="comment">// `sync` => also produce `Arc` downcasts.
|
|
|
|
// Concrete types implementing Base.
|
|
</span><span class="attr">#[derive(Debug)]
|
|
</span><span class="kw">struct </span>Foo(u32);
|
|
<span class="kw">impl </span>Base <span class="kw">for </span>Foo {}
|
|
<span class="attr">#[derive(Debug)]
|
|
</span><span class="kw">struct </span>Bar(f64);
|
|
<span class="kw">impl </span>Base <span class="kw">for </span>Bar {}
|
|
|
|
<span class="kw">fn </span>main() {
|
|
<span class="comment">// Create a trait object.
|
|
</span><span class="kw">let </span><span class="kw-2">mut </span>base: Box<Base> = Box::new(Foo(<span class="number">42</span>));
|
|
|
|
<span class="comment">// Try sequential downcasts.
|
|
</span><span class="kw">if let </span><span class="prelude-val">Some</span>(foo) = base.downcast_ref::<Foo>() {
|
|
<span class="macro">assert_eq!</span>(foo.<span class="number">0</span>, <span class="number">42</span>);
|
|
} <span class="kw">else if let </span><span class="prelude-val">Some</span>(bar) = base.downcast_ref::<Bar>() {
|
|
<span class="macro">assert_eq!</span>(bar.<span class="number">0</span>, <span class="number">42.0</span>);
|
|
}
|
|
|
|
<span class="macro">assert!</span>(base.is::<Foo>());
|
|
|
|
<span class="comment">// Fail to convert `Box<Base>` into `Box<Bar>`.
|
|
</span><span class="kw">let </span>res = base.downcast::<Bar>();
|
|
<span class="macro">assert!</span>(res.is_err());
|
|
<span class="kw">let </span>base = res.unwrap_err();
|
|
<span class="comment">// Convert `Box<Base>` into `Box<Foo>`.
|
|
</span><span class="macro">assert_eq!</span>(<span class="number">42</span>, base.downcast::<Foo>().map_err(|<span class="kw">_</span>| <span class="string">"Shouldn't happen."</span>).unwrap().<span class="number">0</span>);
|
|
|
|
<span class="comment">// Also works with `Rc`.
|
|
</span><span class="kw">let </span><span class="kw-2">mut </span>rc: Rc<Base> = Rc::new(Foo(<span class="number">42</span>));
|
|
<span class="macro">assert_eq!</span>(<span class="number">42</span>, rc.downcast_rc::<Foo>().map_err(|<span class="kw">_</span>| <span class="string">"Shouldn't happen."</span>).unwrap().<span class="number">0</span>);
|
|
|
|
<span class="comment">// Since this trait is `Sync`, it also supports `Arc` downcasts.
|
|
</span><span class="kw">let </span><span class="kw-2">mut </span>arc: Arc<Base> = Arc::new(Foo(<span class="number">42</span>));
|
|
<span class="macro">assert_eq!</span>(<span class="number">42</span>, arc.downcast_arc::<Foo>().map_err(|<span class="kw">_</span>| <span class="string">"Shouldn't happen."</span>).unwrap().<span class="number">0</span>);
|
|
}</code></pre></div>
|
|
<h2 id="example-with-a-generic-trait-with-associated-types-and-constraints"><a class="doc-anchor" href="#example-with-a-generic-trait-with-associated-types-and-constraints">§</a>Example with a generic trait with associated types and constraints</h2>
|
|
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="comment">// Can call macro via namespace since rust 1.30.
|
|
</span><span class="kw">extern crate </span>downcast_rs;
|
|
<span class="kw">use </span>downcast_rs::Downcast;
|
|
|
|
<span class="comment">// To create a trait with downcasting methods, extend `Downcast` or `DowncastSync`
|
|
// and run `impl_downcast!()` on the trait.
|
|
</span><span class="kw">trait </span>Base<T: Clone>: Downcast { <span class="kw">type </span>H: Copy; }
|
|
<span class="macro">downcast_rs::impl_downcast!</span>(Base<T> assoc H <span class="kw">where </span>T: Clone, H: Copy);
|
|
<span class="comment">// or: impl_downcast!(concrete Base<u32> assoc H=f32)
|
|
|
|
// Concrete types implementing Base.
|
|
</span><span class="kw">struct </span>Foo(u32);
|
|
<span class="kw">impl </span>Base<u32> <span class="kw">for </span>Foo { <span class="kw">type </span>H = f32; }
|
|
<span class="kw">struct </span>Bar(f64);
|
|
<span class="kw">impl </span>Base<u32> <span class="kw">for </span>Bar { <span class="kw">type </span>H = f32; }
|
|
|
|
<span class="kw">fn </span>main() {
|
|
<span class="comment">// Create a trait object.
|
|
</span><span class="kw">let </span><span class="kw-2">mut </span>base: Box<Base<u32, H=f32>> = Box::new(Bar(<span class="number">42.0</span>));
|
|
|
|
<span class="comment">// Try sequential downcasts.
|
|
</span><span class="kw">if let </span><span class="prelude-val">Some</span>(foo) = base.downcast_ref::<Foo>() {
|
|
<span class="macro">assert_eq!</span>(foo.<span class="number">0</span>, <span class="number">42</span>);
|
|
} <span class="kw">else if let </span><span class="prelude-val">Some</span>(bar) = base.downcast_ref::<Bar>() {
|
|
<span class="macro">assert_eq!</span>(bar.<span class="number">0</span>, <span class="number">42.0</span>);
|
|
}
|
|
|
|
<span class="macro">assert!</span>(base.is::<Bar>());
|
|
}</code></pre></div>
|
|
</div></details><h2 id="macros" class="section-header">Macros<a href="#macros" class="anchor">§</a></h2><ul class="item-table"><li><div class="item-name"><a class="macro" href="macro.impl_downcast.html" title="macro downcast_rs::impl_downcast">impl_<wbr>downcast</a></div><div class="desc docblock-short">Adds downcasting support to traits that extend <code>downcast::Downcast</code> by defining forwarding
|
|
methods to the corresponding implementations on <code>std::any::Any</code> in the standard library.</div></li></ul><h2 id="traits" class="section-header">Traits<a href="#traits" class="anchor">§</a></h2><ul class="item-table"><li><div class="item-name"><a class="trait" href="trait.Downcast.html" title="trait downcast_rs::Downcast">Downcast</a></div><div class="desc docblock-short">Supports conversion to <code>Any</code>. Traits to be extended by <code>impl_downcast!</code> must extend <code>Downcast</code>.</div></li><li><div class="item-name"><a class="trait" href="trait.DowncastSync.html" title="trait downcast_rs::DowncastSync">Downcast<wbr>Sync</a></div><div class="desc docblock-short">Extends <code>Downcast</code> to support <code>Sync</code> traits that thus support <code>Arc</code> downcasting as well.</div></li></ul></section></div></main></body></html> |