<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Brandon Minor</title>
    <description>The latest articles on Forem by Brandon Minor (@bminortx).</description>
    <link>https://forem.com/bminortx</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F517589%2F74b25d20-e9ac-43f1-8d15-71fc890455b3.png</url>
      <title>Forem: Brandon Minor</title>
      <link>https://forem.com/bminortx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bminortx"/>
    <language>en</language>
    <item>
      <title>Making Great Docs with Rustdoc</title>
      <dc:creator>Brandon Minor</dc:creator>
      <pubDate>Tue, 16 Mar 2021 00:26:01 +0000</pubDate>
      <link>https://forem.com/tangramvision/making-great-docs-with-rustdoc-4j5k</link>
      <guid>https://forem.com/tangramvision/making-great-docs-with-rustdoc-4j5k</guid>
      <description>&lt;p&gt;At &lt;a href="https://www.tangramvision.com"&gt;Tangram Vision&lt;/a&gt;, One of the things we've come to love about Rust is the tight integration of the tooling and ecosystem. Rustdoc, the official documentation system, is no exception to this; it's simple to use, creates beautiful pages, and makes documentation a joy. &lt;/p&gt;

&lt;p&gt;We take documentation seriously. Documentation is for many the first entry point into the code, and good documentation is a primary driver of code adoption (along with functionality). This left us wondering: what &lt;em&gt;are&lt;/em&gt; the best practices for making quality Rust documentation via Rustdoc? Through the course of our research, we found a couple of key resources that the community has provided:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html"&gt;The rustdoc book&lt;/a&gt;: A great place to start if you're looking to learn how to write documentation in your crates.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://rust-lang.github.io/rfcs/0505-api-comment-conventions.html"&gt;RFC 505: API Comment Conventions&lt;/a&gt; and &lt;a href="https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html"&gt;RFC 1574: More API Documentation Conventions&lt;/a&gt;: Explanations on how the &lt;a href="https://www.rust-lang.org/governance/teams/core"&gt;core Rust team&lt;/a&gt; documents the standard library and language interfaces.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, while these are useful resources, we felt that a more approachable guide to crate documentation would be helpful to those starting out with their own crates. Through the course of this article, we'll find that Rust's crate+module structure naturally facilitates great documentation creation; we simply play to Rust's strengths.  &lt;/p&gt;

&lt;p&gt;Note: this guide is about achieving &lt;strong&gt;good documentation quality&lt;/strong&gt;. It does not lay out any technical or formatting guidelines. For instance, we internally wrap our documentation at 120 characters a line... but a 120-character line limit won't do much to improve bad docs. &lt;/p&gt;

&lt;p&gt;We assume a bit of knowledge with rustdocs below. If you are unfamiliar with the program, we encourage you to read the rustdoc book linked above as a primer.&lt;/p&gt;

&lt;h1&gt;
  
  
  Goals of Documentation
&lt;/h1&gt;

&lt;p&gt;Here at &lt;a href="https://www.tangramvision.com"&gt;Tangram Vision&lt;/a&gt;, we structure our documentation around two ideas: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;What&lt;/em&gt;: Explaining what was built&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;How&lt;/em&gt;: Explaining how to use it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anything beyond this is generally not helpful, for one singular reason: our documentation assumes that our users know Rust. We believe this assumption is critical to creating good documentation around the What and How. The docs should rarely discuss &lt;em&gt;why&lt;/em&gt; a decision was made, unless that decision goes against intuition; instead, the docs only explain how to capitalize on that decision in one's own code. &lt;/p&gt;

&lt;p&gt;This guideline of User Knowledge naturally leads us to another rule: &lt;em&gt;Keep It Short.&lt;/em&gt; The aim is to be succinct by telling the user the What and the How in as little time as possible. This often means using simple, active language and avoiding technical jargon. If a longer discussion is needed, make sure to put the What and the How first, and the discussion after. &lt;/p&gt;

&lt;p&gt;Both the What and the How can be seen at all levels of documentation in Rust. We'll see how best to organize that in a large repository below while maintaining consistent style and language. &lt;/p&gt;

&lt;h1&gt;
  
  
  Documentation Across a Crate
&lt;/h1&gt;

&lt;p&gt;There's a natural top-down pattern to follow for Rust documentation. The top level &lt;code&gt;lib.rs&lt;/code&gt; or &lt;code&gt;main.rs&lt;/code&gt; is the first things users see, so it's the perfect spot to introduce the big What ideas. As the documentation gets more into the weeds, from modules to types to functions, documentation shifts more to the How. We'll see this play out as we discuss the different levels below. &lt;/p&gt;

&lt;p&gt;We have added relevant links to our own documentation in the &lt;a href="https://gitlab.com/tangram-vision-oss/realsense-rust"&gt;realsense-rust&lt;/a&gt; crate maintained by Tangram Vision OSS. Check these out for added context. &lt;/p&gt;

&lt;h2&gt;
  
  
  Crate
&lt;/h2&gt;

&lt;p&gt;Crate-level example &lt;a href="https://gitlab.com/tangram-vision-oss/realsense-rust/-/blob/main/src/lib.rs"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The crate documentation in &lt;code&gt;lib.rs&lt;/code&gt; or &lt;code&gt;main.rs&lt;/code&gt; should describe the purpose of the crate (the big What) alongside instructions and examples for getting started (the big How). This is a place for big ideas, since the details will come later in the lower levels. Any counter-intuitive design decisions or common gotchas should also be documented here, but remember: the What and the How always come first, and discussion follows.  &lt;/p&gt;

&lt;p&gt;Notice how the first sections are &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;li&gt;Features&lt;/li&gt;
&lt;li&gt;Usage&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;...all explaining the big What and How. The documentation goes into more detail afterwards, with headings like "Architecture &amp;amp; Guiding Principles", "Prefer Rust-native types to types used through the FFI", etc. However, these sections are there only to explain the &lt;em&gt;non-intuitive&lt;/em&gt; design decisions that go behind creating an FFI interface like this one. For those that don't care, the What and How are presented first, front and center. &lt;/p&gt;

&lt;h2&gt;
  
  
  Modules
&lt;/h2&gt;

&lt;p&gt;Module-level example &lt;a href="https://gitlab.com/tangram-vision-oss/realsense-rust/-/blob/main/src/pipeline.rs"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Modules should contain more direct documentation than the crate itself. The focus again should be on describing the types found in that module and how they interact with the rest of the crate. From this alone, users should understand the Why, i.e. why they would reach for a module from your crate.&lt;/p&gt;

&lt;p&gt;This can get a bit trickier with sub-modules. Avoid deeply nested sub-modules, since they complicate the structure of a crate. Modules with sub-modules more than two layers deep can probably be flattened out. Exceptions exist, but if this layering is needed, it makes sense to add a &lt;strong&gt;Why&lt;/strong&gt; discussion to explain what made this necessary. &lt;/p&gt;

&lt;h2&gt;
  
  
  Types
&lt;/h2&gt;

&lt;p&gt;Type-level example &lt;a href="https://gitlab.com/tangram-vision-oss/realsense-rust/-/blob/main/src/frame/image.rs#L47"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Types are our primary way of defining abstraction and ontological separations in our code. Documentation here should focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Construction of the type (when and how, if users are allowed to construct their own).&lt;/li&gt;
&lt;li&gt;Destruction / dropping the type → what happens when you drop a value of a given type? If you don't implement the &lt;code&gt;Drop&lt;/code&gt; trait, then this is probably OK to ignore.&lt;/li&gt;
&lt;li&gt;Performance characteristics of the type, if it is a data structure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As one can see, the documentation naturally de-emphasizes the What and builds on the How as we go down. Again, counter-intuitive or non-obvious cases might have a Why, but the What and the How together should suffice.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Functions
&lt;/h2&gt;

&lt;p&gt;Function-level example &lt;a href="https://gitlab.com/tangram-vision-oss/realsense-rust/-/blob/main/src/frame/image.rs#L166"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last thing to document is functions and associated functions (functions in &lt;code&gt;impl&lt;/code&gt; blocks). This could include constructors, mutable functions, or data returned by accessors on a type or types. Semantic and code examples are especially welcome here because they describe the How in practical terms. &lt;/p&gt;

&lt;h1&gt;
  
  
  Common Sections Across a Crate
&lt;/h1&gt;

&lt;p&gt;Crate and module level documentation can be broken down into multiple sections with heading levels 1 (&lt;code&gt;#&lt;/code&gt; in markdown), 2 (&lt;code&gt;##&lt;/code&gt;), and 3 (&lt;code&gt;###&lt;/code&gt;). As you move towards documenting types and functions, aim to be as flat as possible; only use heading level 1 if a section is needed. &lt;/p&gt;

&lt;p&gt;These headings are ordered below (in our humble opinion) according to their usefulness for the user in conveying the What and the How for a Rust crate. It's important to note that not all headings need to be present at all times. If it doesn't make sense, don't add it, since it just increases the cognitive burden on the user. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;# Examples&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Examples are, by far, the easiest and most concise way to convey How. They are welcome at all levels: module, type, function, or crate. Write examples for both common use cases and corner cases, like with &lt;code&gt;Error&lt;/code&gt; or &lt;code&gt;None&lt;/code&gt; results. &lt;/p&gt;

&lt;p&gt;Examples in &lt;code&gt;rustdoc&lt;/code&gt; documentation will compile and run as doc-tests. This is an &lt;strong&gt;important point&lt;/strong&gt;: all code in the documentation will actually compile and run! This means they automatically provide users with starting point for understanding. This is one of Rustdoc's greatest strengths, and it should be utilized whenever possible.  &lt;/p&gt;

&lt;p&gt;a frame of reference for the HowMake these examples functional code whenever possible. If this is &lt;em&gt;not&lt;/em&gt; possible, e.g. with an example explaining improper usage, tha frame of reference for the Howen use the heading &lt;code&gt;text&lt;/code&gt; or &lt;code&gt;ignore&lt;/code&gt; next to the code block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;/// # Examples&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="c"&gt;/// '''ignore&lt;/span&gt;
&lt;span class="c"&gt;/// let bummer = this_code_wont_work(); // but it's an illustrative example.&lt;/span&gt;
&lt;span class="c"&gt;/// '''&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the heading is "Examples", plural. Be consistent with the plurality here. Even if there is only one example, the consistency helps with searching.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;# Errors&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;At their best, Errors help a user understand why a certain action is prevented by the crate and how to respond to it. It's a rare instance where explaining the &lt;em&gt;Why&lt;/em&gt; is not just encouraged, but necessary for proper use.  &lt;/p&gt;

&lt;p&gt;At a function level, this section is only needed if that function returns a &lt;code&gt;Result&lt;/code&gt; type. In this case, it describes the type returned and when the error should be expected, e.g. an invalid internal state, Foreign Function Interface (FFI) interactions, bad arguments, etc.&lt;/p&gt;

&lt;p&gt;Make errors actionable by either passing them to a higher level function or allowing a reaction from the caller. It is easier for users to understand how they got there in the first place by writing error types with reaction in mind. Moreover, if a caller can't act on an error, then there's not a strong reason to present it in the first place.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;# Safety&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;First and foremost: Try to minimize unsafe interfaces where possible. Rust is a language built on memory safety, and violating this tenet should only be done with conscious intention. The Safety section should convey that intention. &lt;/p&gt;

&lt;p&gt;When documenting Safety, be explicit about what is "unsafe" about the interface and explain best practices for its use with safe code. If possible, try to specify undefined behavior if an unsafe interface will leave your program in an undefined state.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;# Panics&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Use this section if a function can &lt;code&gt;panic!&lt;/code&gt;. Complete coverage would aim to document any and all calls to &lt;code&gt;.unwrap()&lt;/code&gt;, &lt;code&gt;debug_assert!&lt;/code&gt;, etc. &lt;/p&gt;

&lt;p&gt;Complete coverage is a good goal to aim for, but realize that a &lt;code&gt;panic!&lt;/code&gt; call isn't always necessary. Many cases can be guarded against with small code changes. Returning &lt;code&gt;Result&lt;/code&gt; types can avoid this entirely in exchange for better error handling. Low-level FFI calls can unwrap and &lt;code&gt;panic!&lt;/code&gt; if passed a null pointer; yet this can be prevented if you start with &lt;code&gt;NonNull&amp;lt;T&amp;gt;&lt;/code&gt; as the input, making an &lt;code&gt;unwrap()&lt;/code&gt; call superfluous. &lt;/p&gt;

&lt;p&gt;In any case, you should aim to have all error cases implemented whenever possible. If there is a case that can cause a &lt;code&gt;panic!&lt;/code&gt;, list it in the docs.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;# Lifetimes&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Include a Lifetimes section if a type or function has special lifetime considerations that need to be taken into consideration by the user. Most of the time, a lifetime itself doesn't need describing; again, always assume users know Rust. Rather, this section should explain why the lifetime has been modeled in a certain way.&lt;/p&gt;

&lt;p&gt;Rule of thumb: If you only have one lifetime (explicit or implicit), it probably doesn't need documentation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;/// Wrapper type for an underlying C-FFI pointer&lt;/span&gt;
&lt;span class="c"&gt;/// &lt;/span&gt;
&lt;span class="c"&gt;/// # Lifetimes&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="c"&gt;/// The underlying pointer is generated from some C-FFI.&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="c"&gt;/// Adding a lifetime that only references phantom data may seem strange&lt;/span&gt;
&lt;span class="c"&gt;/// and artificial. However, enforcing this lifetime is useful because&lt;/span&gt;
&lt;span class="c"&gt;/// the C API may have undefined behavior or odd semantics outside of&lt;/span&gt;
&lt;span class="c"&gt;/// whatever "assumed" lifetime the library writers intended. We make&lt;/span&gt;
&lt;span class="c"&gt;/// this explicit in Rust with the hope of preventing mistakes in using&lt;/span&gt;
&lt;span class="c"&gt;/// this API. &lt;/span&gt;
&lt;span class="c"&gt;/// &lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;SomeType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/// Pointer to data from a C-FFI&lt;/span&gt;
    &lt;span class="c"&gt;///&lt;/span&gt;
    &lt;span class="c"&gt;/// We need to store this as NonNull because its use in the C API&lt;/span&gt;
    &lt;span class="c"&gt;/// is covariant.&lt;/span&gt;
    &lt;span class="n"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NonNull&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;os&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;c_void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c"&gt;/// Phantom to annotate this type with an explicit lifetime.&lt;/span&gt;
    &lt;span class="c"&gt;///&lt;/span&gt;
    &lt;span class="c"&gt;/// See type documentation for why this is done.&lt;/span&gt;
    &lt;span class="mi"&gt;_&lt;/span&gt;&lt;span class="n"&gt;phantom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;marker&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PhantomData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above example shows one instance in where a (single) strange lifetime is applied to enforce Rust's lifetime rules on a type. The lifetime &lt;em&gt;seems&lt;/em&gt; superfluous, but may exist because there is some implicit assumption in C that is being made more explicit here.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;# Arguments&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Avoid listing arguments explicitly. Instead, names and types themselves should adequately describe arguments and their relationships. &lt;/p&gt;

&lt;p&gt;That being said, an &lt;code&gt;# Arguments&lt;/code&gt; section can make sense if there is a non-obvious assumption about the arguments or their types that needs to be made explicit, like if passing in certain values for a type invokes &lt;em&gt;undefined behaviour.&lt;/em&gt; In such a case, an &lt;code&gt;# Arguments&lt;/code&gt; or &lt;code&gt;# Generic Arguments&lt;/code&gt; section is useful to clarify that care is needed when passing in data. &lt;/p&gt;

&lt;p&gt;For generic arguments that may require trait bounds, "document" these by adding &lt;code&gt;where&lt;/code&gt; clauses to your function or type. This is much more descriptive and useful, and has the added benefit of your compiler doing some of the work to validate these bounds for you.&lt;/p&gt;

&lt;p&gt;Take a look at &lt;a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.reserve"&gt;the standard library&lt;/a&gt; for examples of good argument names and types.&lt;/p&gt;

&lt;h1&gt;
  
  
  A Few Last Details
&lt;/h1&gt;

&lt;p&gt;The below points deserve to be noted, but don't necessarily fit into any specific framework. &lt;/p&gt;

&lt;h2&gt;
  
  
  Document Traits, Not Trait Implementations
&lt;/h2&gt;

&lt;p&gt;Traits are trickier than regular types and associated functions. Since a trait can be applied to multiple types (even those outside of its crate), don't document implementations of a trait. Instead, document the trait itself. &lt;/p&gt;

&lt;p&gt;Good&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;/// A trait providing methods for adding different types of numbers to a type.&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;NumberAdder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/// Adds an integer to the type&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;add_integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c"&gt;/// Adds a float to the type&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;add_float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bad&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;NumberAdder&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/// Adds an integer to Foo&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;add_integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;/// Adds a float to Foo&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;add_float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Traits are used primarily in generic code, so users will look at the trait itself to understand the interfaces. Any two types implementing the same trait should share common functionality; if two implementations of a trait require vastly differing documentation, the trait itself may not be modeled correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  References Should Always Be Links
&lt;/h2&gt;

&lt;p&gt;Whenever a reference is made, whether it be to another part of the documentation, a website, a paper, or another crate: add a link to it. This applies even when referencing a common type found in the standard library (e.g. &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Vec&lt;/code&gt;, etc.).&lt;/p&gt;

&lt;p&gt;Linking to other parts of the documentation avoids repeating information. It is also an easy way to point to higher level architecture decisions that might affect the lower level documentation. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;rustdoc&lt;/code&gt; handles documentation links natively. Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;/// See [`String`](std::string::String) documentation for more details.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Examples and Resources
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Open-Source Documentation Examples
&lt;/h2&gt;

&lt;p&gt;We've worked hard at &lt;a href="https://www.tangramvision.com"&gt;Tangram Vision&lt;/a&gt; to follow our own guidelines and create world-class Rust documentation. You can read the fruits of our labor by visiting any of the repositories at our &lt;a href="https://gitlab.com/tangram-vision-oss"&gt;Open-Source software group&lt;/a&gt;. The &lt;a href="https://gitlab.com/tangram-vision-oss/realsense-rust"&gt;RealSense Rust&lt;/a&gt; package that we maintain is some of our most complete documentation, and acts a good starting point. &lt;/p&gt;

&lt;h2&gt;
  
  
  Templates for Types and Functions
&lt;/h2&gt;

&lt;p&gt;Most of these examples come in the form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;/// Summary line -&amp;gt; what is this&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="c"&gt;/// Longer description of what is returned, or semantics regarding the type.&lt;/span&gt;
&lt;span class="c"&gt;/// ...&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="c"&gt;/// # Examples&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="c"&gt;/// '''&lt;/span&gt;
&lt;span class="c"&gt;/// &amp;lt;some-rust-code&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;/// '''&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Types
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;/// Type for describing errors that result from trying to set an option  &lt;/span&gt;
&lt;span class="c"&gt;/// on a sensor.&lt;/span&gt;
&lt;span class="nd"&gt;#[derive(Debug)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;SetOptionError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/// The option is not supported on the sensor.&lt;/span&gt;
    &lt;span class="n"&gt;OptionNotSupported&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c"&gt;/// The option is supported on the sensor but is immutable.&lt;/span&gt;
    &lt;span class="n"&gt;OptionIsImmutable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c"&gt;/// Setting the option failed due to an internal exception.&lt;/span&gt;
    &lt;span class="c"&gt;///&lt;/span&gt;
    &lt;span class="c"&gt;/// See the enclosed string for a reason why the internal exception occurred.&lt;/span&gt;
    &lt;span class="nf"&gt;CouldNotSetOption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Functions
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;/// Sets a `value` for the provided `option` in `self`. &lt;/span&gt;
&lt;span class="c"&gt;/// &lt;/span&gt;
&lt;span class="c"&gt;/// Returns `Ok(())` on success, otherwise returns an error.&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="c"&gt;/// # Errors&lt;/span&gt;
&lt;span class="c"&gt;/// &lt;/span&gt;
&lt;span class="c"&gt;/// Returns [`OptionNotSupported`](SetOptionError::OptionNotSupported) if the&lt;/span&gt;
&lt;span class="c"&gt;/// option is not supported on this sensor.&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="c"&gt;/// Returns [`OptionIsImmutable`](SetOptionError::OptionIsImmutable) if the&lt;/span&gt;
&lt;span class="c"&gt;/// option is supported but is immutable.&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="c"&gt;/// Returns [`CouldNotSetOption`](SetOptionError::CouldNotSetOption) if the&lt;/span&gt;
&lt;span class="c"&gt;/// option could not be set due to an internal exception.&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="c"&gt;/// # Examples&lt;/span&gt;
&lt;span class="c"&gt;/// &lt;/span&gt;
&lt;span class="c"&gt;/// '''&lt;/span&gt;
&lt;span class="c"&gt;/// let option = SomeOption::Foo;&lt;/span&gt;
&lt;span class="c"&gt;/// let value = 100.5;&lt;/span&gt;
&lt;span class="c"&gt;/// &lt;/span&gt;
&lt;span class="c"&gt;/// match sensor.set_option(option, value) {&lt;/span&gt;
&lt;span class="c"&gt;///     Ok(()) =&amp;gt; {&lt;/span&gt;
&lt;span class="c"&gt;///         println!("Success!");&lt;/span&gt;
&lt;span class="c"&gt;///     }&lt;/span&gt;
&lt;span class="c"&gt;///     Err(SetOptionError::OptionNotSupported) =&amp;gt; {&lt;/span&gt;
&lt;span class="c"&gt;///         println!("This option isn't supported, try another one!");&lt;/span&gt;
&lt;span class="c"&gt;///     }&lt;/span&gt;
&lt;span class="c"&gt;///     Err(SetOptionError::OptionIsImmutable) =&amp;gt; {&lt;/span&gt;
&lt;span class="c"&gt;///         println!("This option is immutable, we can't set it!");&lt;/span&gt;
&lt;span class="c"&gt;///     }&lt;/span&gt;
&lt;span class="c"&gt;///     _ =&amp;gt; {&lt;/span&gt;
&lt;span class="c"&gt;///         panic!();&lt;/span&gt;
&lt;span class="c"&gt;///     }&lt;/span&gt;
&lt;span class="c"&gt;/// }&lt;/span&gt;
&lt;span class="c"&gt;/// '''&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;set_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SomeOption&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;SetOptionError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// implementation here&lt;/span&gt;
    &lt;span class="nd"&gt;unimplemented!&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Bad Documentation
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;/// Get the value associated with the provided Rs2Option for the sensor.&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="c"&gt;/// # Arguments&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="c"&gt;/// - `option` - The option key that we want the associated value of.&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="c"&gt;/// # Returns&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="c"&gt;/// An f32 value corresponding to that option within the librealsense2 library, &lt;/span&gt;
&lt;span class="c"&gt;/// or None if the option is not supported.&lt;/span&gt;
&lt;span class="c"&gt;///&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Rs2Option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why is this bad? &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Arguments section is superfluous, since the names and types of the arguments make their use self-evident. See the Arguments section above.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;# Returns&lt;/code&gt; section isn't needed at all. First off, "Returns" should not be a header category; this information can be more concisely expressed in the function summary. Secondly, the return type that is there (&lt;code&gt;Option&amp;lt;f32&amp;gt;&lt;/code&gt;) makes the possible return values clear already to the user. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A more correct way to write this example would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c"&gt;/// Get the value associated with the provided `option` for the sensor,&lt;/span&gt;
&lt;span class="c"&gt;/// or `None` if no such value exists.&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Rs2Option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cover photo credit: Photo by &lt;a href="https://unsplash.com/@beatriz_perez?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Beatriz Pérez Moya&lt;/a&gt; on &lt;a href="/@beatriz_perez?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>tutorial</category>
      <category>documentation</category>
    </item>
    <item>
      <title>RSBadges: Create Code Badges in Rust</title>
      <dc:creator>Brandon Minor</dc:creator>
      <pubDate>Thu, 11 Feb 2021 19:46:07 +0000</pubDate>
      <link>https://forem.com/tangramvision/rsbadges-create-code-badges-in-rust-2ke0</link>
      <guid>https://forem.com/tangramvision/rsbadges-create-code-badges-in-rust-2ke0</guid>
      <description>&lt;p&gt;We've just launched our first open source project at &lt;a href="https://www.tangramvision.com"&gt;Tangram Vision&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gitlab.com/tangram-vision-oss/rsbadges"&gt;RSBadges&lt;/a&gt; is a Rust-friendly badge generator. The interface strives to be minimal while still providing a feature-rich API. Both the label (the left side) and the message (the right side) of the badge can be customized fully, with the ability to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set text&lt;/li&gt;
&lt;li&gt;Set color using any valid CSS color code&lt;/li&gt;
&lt;li&gt;Embed a link into each side or a link for the whole badge&lt;/li&gt;
&lt;li&gt;Add a logo (in SVG format) from a local source or a URL&lt;/li&gt;
&lt;li&gt;Embed that logo's data into the badge directly&lt;/li&gt;
&lt;li&gt;Set the style of badge, as described in &lt;a href="http://shields.io/"&gt;Shields.io&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RSBadges can be used as an API or a command line interface (CLI).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gitlab.com/tangram-vision-oss/rsbadges"&gt;Check it out on GitLab here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Got feedback? We'd love to hear it!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
