Trait `From<u8>` is not implemented for `Bson`

I am trying to understand mongodb driver for rust.
When building this query

doc! { "section_id": section_id }

I get this error:

  --> src/main.rs:61:30
   |
61 |         doc! { "section_id": section_id }
   |         ---------------------^^^^^^^^^^--
   |         |                    |
   |         |                    the trait `From<u8>` is not implemented for `Bson`
   |         required by a bound introduced by this call
   |
   = help: the following other types implement trait `From<T>`:
             <Bson as From<&T>>
             <Bson as From<&[T]>>
             <Bson as From<&str>>
             <Bson as From<Regex>>
             <Bson as From<Vec<T>>>
             <Bson as From<[u8; 12]>>
             <Bson as From<bool>>
             <Bson as From<chrono::datetime::DateTime<T>>>
           and 19 others

section_id is from the following struct

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
struct ChaptersFilterOptions {
    section_id: Option<u8>
}

How do I solve this? Do I have to implement From for every type that I will use?

The doc! macro requires that all the types you use with it can be converted to the Bson type, which is done with the From trait. In other words, Bson needs to implement From<Option<u8>> for you to be able to use section_id.

The reason the error message mentions From<u8> is because the Bson implements From for all Option<T> where T can be converted into Bson (this implementation is here: Bson in bson - Rust). So From<Option<u8>> is implemented for Bson if From<u8> is implemented.

You can't implement From<u8> for Bson because neither the trait nor type are local to your crate. From comes from std and Bson from bson. Rust doesn't allow you to implement foreign traits for foreign types.

You can convert section_id to some other type T that does implement From<T> for Bson, like u32:

doc! { "section_id": section_id.map(u32::from) }; // turns section_id from Option<u8> into Option<u32>
3 Likes

@Heliozoa, thanks for the reply. I tried your suggestion. It is not working. As it turns out, I did not clearly communicated my code. In the following code, I face problem in the match expression in build_chapters_query_and_options function. .map does not work because, it is not an Option type, I suppose!:

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
 
   let client_uri = ...;

   let options =
      ClientOptions::parse_with_resolver_config(&client_uri, ResolverConfig::cloudflare())
         .await?;
   let client = Client::with_options(options)?;

   print_find_options();

   Ok(())
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
struct ChaptersFilterOptions {
    section_id: Option<u8>
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
struct PaginationOptions {
    skip: i64,
    limit: i64
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
struct ChaptersQueryOptions {
    filter_options: ChaptersFilterOptions,
    pagination_options: PaginationOptions
}

pub fn build_chapters_query_and_options(query_options: ChaptersQueryOptions) -> (Document, FindOptions) {
    
    let filter_options = query_options.filter_options;
    let pagination_options = query_options.pagination_options;

    let find_options = FindOptions::builder()
        .skip(pagination_options.skip)
        .limit(pagination_options.limit).build();

    let filter = match filter_options.section_id {
      Some(section_id) => {
        doc! { "section_id": section_id }
      }
      None => {
        doc! { }
      }
    };
    
    return (filter, find_options);

}

fn print_find_options() {

    let query_options = ChaptersQueryOptions {
        filter_options: ChaptersFilterOptions {
            section_id: Some(10)
        },
        pagination_options: PaginationOptions {
            skip: 0,
            limit: 10,
        }
    };
    
    let (options) = build_chapters_query_and_options(query_options);

    println!("{:?}", options);

}

@Heliozoa. Never mind! I have found the issue. My bad that I did not understood what type of parameter is needed for .skip & .limit methods. They are Option u64, i64 respectively. Similarly, for some reason u8 did not work. Mongodb driver only expects u32. I've sorted them out! Thanks for your time.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.