bson_comp

Crates.iobson_comp
lib.rsbson_comp
version0.1.0
created_at2025-12-23 13:30:55.887374+00
updated_at2025-12-23 13:30:55.887374+00
descriptionA derive macro that implements `Into` for a struct or enum.
homepage
repositoryhttps://github.com/h01-team/bson_comp
max_upload_size
id2001500
size8,925
Harihar Nautiyal (harihar-nautiyal)

documentation

https://docs.rs/bson_comp/0.1.0

README

bson_comp

Latest Version

Stop fighting the doc! macro. Make your types generic-compatible.

If you work with MongoDB in Rust, you've definitely hit this wall. You have a nice, strongly-typed Enum or Struct, and you just want to use it in a query.

The Problem

You try to do this:

let filter = doc! { "role": Role::Admin };

And the compiler screams at you with Error E0277:

the trait bound Bson: std::convert::From<Role> is not satisfied
required for Role to implement Into<Bson>

So you end up writing this boilerplate everywhere:

// ❌ The Ugly Way
// Manual conversion every time you use it.
let filter = doc! { 
    "role": bson::to_bson(&Role::Admin).unwrap() 
};

The Solution

bson_comp (BSON Compatibility) handles that boilerplate for you. It implements Into<Bson> for your types so they fit right into the doc! macro.

// ✅ The Clean Way
let filter = doc! { "role": Role::Admin };

Installation

Add this to your Cargo.toml:

[dependencies]
bson_comp = "0.1"
serde = { version = "1.0", features = ["derive"] }

How to use it

1. For Enums (The most common use case)

Perfect for status flags, user roles, or category types.

use serde::{Serialize, Deserialize};
use bson_comp::BsonComp;
use bson::doc;

#[derive(Serialize, Deserialize, BsonComp)]
#[serde(rename_all = "UPPERCASE")] // Optional: controls how it looks in Mongo
enum Role {
    Admin,
    User,
}

fn main() {
    // Works natively in doc!
    let query = doc! { 
        "role": Role::Admin,
        "is_active": true
    };
    
    // Output: { "role": "ADMIN", "is_active": true }
}

2. For Structs

Useful when embedding objects inside other documents.

use serde::Serialize;
use bson_comp::BsonComp;
use bson::doc;

#[derive(Serialize, BsonComp)]
struct Address {
    city: String,
    zip: u32,
}

fn main() {
    let my_address = Address { 
        city: "New York".to_string(), 
        zip: 10001 
    };

    // Embed it directly
    let profile = doc! {
        "username": "alice",
        "address": my_address
    };
}

How it works

Rust's "Orphan Rules" prevent you from implementing From<YourType> for Bson because you don't own the bson crate.

However, the doc! macro accepts anything that implements Into<Bson>. Since Into is a generic trait, you are allowed to implement it for your own types.

This macro simply generates:

impl Into<bson::Bson> for YourType {
    fn into(self) -> bson::Bson {
        bson::to_bson(&self).expect("Failed to serialize type for BSON macro")
    }
}

Requirements

  1. Your type must derive serde::Serialize.
  2. It panics if serialization fails (which shouldn't happen for standard Enums/Structs unless you have custom serialization logic that fails).

License

MIT. Enjoy clean code.

Commit count: 0

cargo fmt