[Canonical page](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/id/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# Id

The id of a task, link, calendar, resource or assignment. An `Id` holds a number or a string and compares like a JavaScript object key, so `1` and `"1"` are the same id. Build one with `.into()` from a `&str`, `String`, `f64` or `i32` wherever an `Id` is expected, or name a variant directly.

## Declaration

```rust
#[derive(Clone, Debug)]
pub enum Id {
    Num(f64),
    Str(String),
}

impl PartialEq for Id
impl Eq for Id
impl Hash for Id
impl Display for Id
impl From<&str> for Id
impl From<String> for Id
impl From<f64> for Id
impl From<i32> for Id
```

`Id` doesn't implement `Default`, `Copy` or `Ord`.

## Variants

| Variant | Description |
|---|---|
| `Num(f64)` | Numeric id. Must be finite: a `NaN` or infinite id in [`ProjectData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md>) fails validation with an [`InputError`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/input-error.md>) of kind `Validation`, message `id must be finite`. |
| `Str(String)` | String id. Any string, including the empty string. |

## Methods

### key

```rust
pub fn key(&self) -> String
```

Returns the normalized key: the string a JavaScript engine uses for this id as an object key.

- `Str(s)` returns `s` unchanged.
- `Num(n)` returns `n` formatted the way JavaScript formats a number. Whole numbers print without a fraction (`1.0` → `"1"`), `0.0` and `-0.0` both print `"0"`, and values from `1e21` up or below `1e-6` use exponent notation (`1e21` → `"1e+21"`).

**Returns** - the normalized key.

### norm

```rust
pub fn norm(&self) -> String
```

Same as [`key`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/id.md#key>).

**Returns** - the normalized key.

## Equality and hashing

Two ids are equal when their [`key`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/id.md#key>) values are equal, and equal ids hash the same:

| Comparison | Result |
|---|---|
| `Id::Num(1.0) == Id::from("1")` | `true` |
| `Id::Num(-0.0) == Id::from("0")` | `true` |
| `Id::Num(1.5) == Id::from("1.5")` | `true` |
| `Id::from("01") == Id::Num(1.0)` | `false` (the key of `1.0` is `"1"`) |

A `HashMap<Id, _>` or `HashSet<Id>` treats `1` and `"1"` as one key.

Numeric ids keep `f64` precision limits. Whole numbers above 2^53 that round to the same `f64` are the same id.

## Display

`Display` writes the [`key`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/id.md#key>), so `format!("{id}")` and `id.to_string()` return the normalized key.

## Serialization

With the `serde` feature, `Id` implements `Serialize` and `Deserialize`:

- `Str` serializes as a JSON string. `Num` serializes as a JSON integer when it's whole (`1.0` → `1`) and as a JSON number otherwise.
- Serializing a non-finite `Num` fails with `id must be finite`.
- A JSON string deserializes to `Str`, and any JSON number to `Num`. Other JSON values fail with the expectation `a string or finite number id`.

```bash
cargo add plen-core --features serde
```

## Example

```rust
use std::collections::HashSet;
use plen_core::Id;

fn main() {
    let a: Id = 1.into();
    let b: Id = "1".into();
    let c = Id::Num(1.5);

    assert_eq!(a, b);
    assert_eq!(a.key(), "1");
    assert_eq!(c.to_string(), "1.5");

    let ids: HashSet<Id> = [a, b, c].into_iter().collect();
    assert_eq!(ids.len(), 2);
}
```

## Related

- [`TaskData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/task-data.md>) - tasks are keyed and parented by `Id`
- [`SchedulingConfig`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/scheduling-config.md>) - `root_id` is an `Id` compared by key
- [`ProjectData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md#validation>) - ids must be unique within each collection
- [Project data](<https://docs.dhtmlx.com/planning-engine/rust/scheduling/project-data.md>) - how numeric and string ids name the same record
- [Quick start](<https://docs.dhtmlx.com/planning-engine/rust/quick-start.md>) - builds ids with `.into()` in a first schedule
