pibtool_stock_data/
wikidata_item_id.rs

1// SPDX-FileCopyrightText: Politik im Blick developers
2// SPDX-FileCopyrightText: Wolfgang Silbermayr <wolfgang@silbermayr.at>
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later OR EUPL-1.2
5
6use std::{fmt::Display, str::FromStr};
7
8use anyhow::{Context as _, ensure};
9use serde_with::{DeserializeFromStr, SerializeDisplay};
10
11/// The identifier of a wikidata item.
12#[derive(Clone, SerializeDisplay, DeserializeFromStr, PartialEq, Eq, PartialOrd, Ord)]
13pub struct WikidataItemId(u64);
14
15impl From<u64> for WikidataItemId {
16    fn from(value: u64) -> Self {
17        Self(value)
18    }
19}
20
21impl FromStr for WikidataItemId {
22    type Err = anyhow::Error;
23
24    fn from_str(s: &str) -> Result<Self, Self::Err> {
25        const MSG: &str =
26            "Wikidata item id must start with a 'Q' followed by a non-negative integer.";
27        ensure!(s.starts_with('Q'), MSG);
28
29        let number_string = &s[1..];
30
31        let value = number_string.parse().context(MSG)?;
32
33        Ok(Self(value))
34    }
35}
36
37impl std::fmt::Debug for WikidataItemId {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        f.debug_tuple("WikidataItemId")
40            .field(&format_args!("Q{}", &self.0))
41            .finish()
42    }
43}
44
45impl Display for WikidataItemId {
46    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47        write!(f, "Q{}", self.0)
48    }
49}