Skip to main content

cp_cli_platform_codeforces/
lib.rs

1//! Public Codeforces problem metadata
2
3mod client;
4mod error;
5
6pub use client::Client;
7pub use error::Error;
8
9/// Credentials generated at Codeforces' API settings page
10#[derive(Clone)]
11pub struct ApiCredentials {
12    key: Box<str>,
13    secret: Box<str>,
14}
15
16impl ApiCredentials {
17    pub fn new(key: impl Into<Box<str>>, secret: impl Into<Box<str>>) -> Result<Self, Error> {
18        let key = key.into();
19        let secret = secret.into();
20        if !valid_api_credential(&key) {
21            return Err(Error::InvalidApiKey);
22        }
23        if !valid_api_credential(&secret) {
24            return Err(Error::InvalidApiSecret);
25        }
26        Ok(Self { key, secret })
27    }
28}
29
30fn valid_api_credential(value: &str) -> bool {
31    !value.is_empty()
32        && value.len() <= 128
33        && value
34            .bytes()
35            .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'_' | b'-'))
36}
37
38#[derive(Debug, PartialEq, Eq)]
39pub struct Problem {
40    pub contest_id: u32,
41    pub index: Box<str>,
42    pub title: Box<str>,
43    pub rating: Option<u16>,
44    pub tags: Vec<Box<str>>,
45    pub solved_count: Option<u32>,
46    pub url: Box<str>,
47    /// Codeforces does not expose statements through its public API
48    pub statement: Option<Box<str>>,
49}
50
51/// A public Codeforces contest, suitable for calendars and status views
52#[derive(Debug, PartialEq, Eq)]
53pub struct Contest {
54    pub id: u32,
55    pub name: Box<str>,
56    pub kind: Box<str>,
57    pub phase: Box<str>,
58    pub start_time_seconds: Option<i64>,
59    pub duration_seconds: Option<u32>,
60}
61
62/// Public account information returned by `user.info`
63#[derive(Debug, PartialEq, Eq)]
64pub struct UserProfile {
65    pub handle: Box<str>,
66    pub first_name: Option<Box<str>>,
67    pub last_name: Option<Box<str>>,
68    pub country: Option<Box<str>>,
69    pub city: Option<Box<str>>,
70    pub organization: Option<Box<str>>,
71    pub rank: Option<Box<str>>,
72    pub rating: Option<i32>,
73    pub max_rank: Option<Box<str>>,
74    pub max_rating: Option<i32>,
75    pub contribution: i32,
76    pub friend_of_count: u32,
77    pub registration_time_seconds: i64,
78    pub last_online_time_seconds: i64,
79}
80
81/// One change in a user's Codeforces rating history
82#[derive(Debug, PartialEq, Eq)]
83pub struct RatingChange {
84    pub contest_id: u32,
85    pub contest_name: Box<str>,
86    pub rank: u32,
87    pub old_rating: i32,
88    pub new_rating: i32,
89    pub rating_update_time_seconds: i64,
90}
91
92/// A public submission returned by `user.status`
93#[derive(Debug, PartialEq, Eq)]
94pub struct Submission {
95    pub id: u64,
96    pub contest_id: Option<u32>,
97    pub creation_time_seconds: i64,
98    pub relative_time_seconds: i64,
99    pub problem_index: Box<str>,
100    pub problem_name: Box<str>,
101    pub programming_language: Box<str>,
102    pub verdict: Option<Box<str>>,
103    pub testset: Box<str>,
104    pub passed_test_count: u32,
105    pub time_consumed_millis: u32,
106    pub memory_consumed_bytes: u64,
107}
108
109/// A public Codeforces blog entry surfaced by the recent activity feed
110#[derive(Debug, PartialEq, Eq)]
111pub struct DiscussionPreview {
112    pub id: u32,
113    pub author: Box<str>,
114    pub title: Box<str>,
115    pub created_time_seconds: i64,
116    pub activity_time_seconds: i64,
117    pub rating: i32,
118    pub tags: Vec<Box<str>>,
119    pub latest_comment: Option<DiscussionComment>,
120    pub url: Box<str>,
121}
122
123/// A public Codeforces blog entry and its public comments
124#[derive(Debug, PartialEq, Eq)]
125pub struct Discussion {
126    pub id: u32,
127    pub author: Box<str>,
128    pub title: Box<str>,
129    pub content_html: Box<str>,
130    pub created_time_seconds: i64,
131    pub modified_time_seconds: Option<i64>,
132    pub rating: i32,
133    pub tags: Vec<Box<str>>,
134    pub comments: Vec<DiscussionComment>,
135    pub url: Box<str>,
136}
137
138/// Metadata and text for one public Codeforces blog comment
139#[derive(Debug, PartialEq, Eq)]
140pub struct DiscussionComment {
141    pub id: u32,
142    pub author: Box<str>,
143    pub content_html: Box<str>,
144    pub created_time_seconds: i64,
145    pub parent_comment_id: Option<u32>,
146    pub rating: i32,
147}
148
149#[cfg(test)]
150mod tests;