Skip to main content

cp_cli_platform_leetcode/
lib.rs

1//! LeetCode platform crate
2
3mod client;
4mod error;
5
6pub use client::Client;
7pub use error::Error;
8
9pub struct Credentials {
10    session: Box<str>,
11    csrf: Box<str>,
12}
13
14impl Credentials {
15    pub fn new(session: &str, csrf: &str) -> Result<Self, Error> {
16        if !valid_credential(session) || !valid_credential(csrf) {
17            return Err(Error::InvalidCredentials);
18        }
19        Ok(Self {
20            session: session.into(),
21            csrf: csrf.into(),
22        })
23    }
24
25    pub(crate) fn session(&self) -> &str {
26        &self.session
27    }
28
29    pub(crate) fn csrf(&self) -> &str {
30        &self.csrf
31    }
32}
33
34impl std::fmt::Debug for Credentials {
35    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        formatter
37            .debug_struct("Credentials")
38            .field("session", &"<redacted>")
39            .field("csrf", &"<redacted>")
40            .finish()
41    }
42}
43
44fn valid_credential(value: &str) -> bool {
45    !value.is_empty()
46        && value.len() <= 4096
47        && value
48            .bytes()
49            .all(|byte| byte.is_ascii_graphic() && byte != b';')
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
53pub enum Difficulty {
54    Easy,
55    Medium,
56    Hard,
57}
58
59#[derive(Debug, PartialEq, Eq)]
60pub struct ProblemSummary {
61    pub number: u32,
62    pub id: Box<str>,
63    pub title: Box<str>,
64    pub difficulty: Difficulty,
65    pub paid_only: bool,
66}
67
68#[derive(Debug, PartialEq, Eq)]
69pub struct SearchResults {
70    pub total: u32,
71    pub problems: Vec<ProblemSummary>,
72}
73
74#[derive(Debug, PartialEq, Eq)]
75pub struct DifficultyCounts {
76    pub all: u32,
77    pub easy: u32,
78    pub medium: u32,
79    pub hard: u32,
80}
81
82#[derive(Debug, PartialEq, Eq)]
83pub struct RecentSubmission {
84    pub id: u64,
85    pub status: Box<str>,
86    pub title: Box<str>,
87    pub slug: Box<str>,
88    pub timestamp: u64,
89    pub language: Box<str>,
90    pub runtime: Option<Box<str>>,
91    pub memory: Option<Box<str>>,
92    pub url: Option<Box<str>>,
93    pub pending: bool,
94}
95
96#[derive(Debug, PartialEq, Eq)]
97pub struct AccountStats {
98    pub username: Box<str>,
99    pub solved: DifficultyCounts,
100    pub accepted_submissions: DifficultyCounts,
101    pub submissions: DifficultyCounts,
102    pub recent_submissions: Vec<RecentSubmission>,
103    pub has_more_submissions: bool,
104}
105
106#[derive(Debug, PartialEq, Eq)]
107pub struct ContestSummary {
108    pub slug: Box<str>,
109    pub title: Box<str>,
110    pub start_time: u64,
111    pub duration_seconds: u32,
112    pub virtual_contest: bool,
113}
114
115#[derive(Debug, PartialEq, Eq)]
116pub struct ContestRegistration {
117    pub slug: Box<str>,
118    pub registered: bool,
119}
120
121#[derive(Debug, PartialEq, Eq)]
122pub struct DiscussionList {
123    pub total: Option<u32>,
124    pub discussions: Vec<DiscussionSummary>,
125}
126
127#[derive(Debug, PartialEq, Eq)]
128pub struct DiscussionSummary {
129    pub id: u32,
130    pub title: Box<str>,
131    pub author: Option<Box<str>>,
132    pub created_at: u64,
133    pub views: u32,
134    pub comments: u32,
135    pub votes: i32,
136}
137
138#[derive(Debug, PartialEq, Eq)]
139pub struct Discussion {
140    pub id: u32,
141    pub title: Box<str>,
142    pub author: Option<Box<str>>,
143    /// Public Markdown supplied by LeetCode
144    pub content: Box<str>,
145    pub created_at: u64,
146    pub updated_at: Option<u64>,
147    pub views: u32,
148    pub comments: u32,
149    pub votes: i32,
150    pub tags: Vec<Box<str>>,
151    pub pinned: bool,
152}
153
154#[derive(Debug)]
155pub struct Problem {
156    pub number: u32,
157    pub id: Box<str>,
158    pub title: Box<str>,
159    /// Problem statement in the HTML format returned by LeetCode
160    pub statement: Box<str>,
161}
162
163#[derive(Debug, PartialEq, Eq)]
164pub struct StarterCode {
165    pub question_id: Box<str>,
166    pub id: Box<str>,
167    pub title: Box<str>,
168    pub snippets: Vec<CodeSnippet>,
169}
170
171#[derive(Debug, PartialEq, Eq)]
172pub struct CodeSnippet {
173    pub language: Box<str>,
174    pub language_slug: Box<str>,
175    pub source: Box<str>,
176}
177
178#[derive(Debug, PartialEq, Eq)]
179pub enum SubmissionState {
180    Pending,
181    Complete(SubmissionResult),
182}
183
184#[derive(Debug, PartialEq, Eq)]
185pub struct SubmissionResult {
186    pub id: u64,
187    pub status: Box<str>,
188    pub accepted: bool,
189    pub runtime: Option<Box<str>>,
190    pub memory: Option<Box<str>>,
191    pub passed: Option<u32>,
192    pub total: Option<u32>,
193    pub message: Option<Box<str>>,
194}
195
196#[derive(Debug, PartialEq, Eq)]
197pub struct TestCases {
198    pub question_id: Box<str>,
199    pub input: Box<str>,
200}
201
202#[derive(Debug, PartialEq, Eq)]
203pub enum RunState {
204    Pending,
205    Complete(RunResult),
206}
207
208#[derive(Debug, PartialEq, Eq)]
209pub struct RunResult {
210    pub id: Box<str>,
211    pub status: Box<str>,
212    pub passed: bool,
213    pub runtime: Option<Box<str>>,
214    pub memory: Option<Box<str>>,
215    pub passed_cases: Option<u32>,
216    pub total_cases: Option<u32>,
217    pub input: Option<Box<str>>,
218    pub output: Option<Box<str>>,
219    pub expected: Option<Box<str>>,
220    pub message: Option<Box<str>>,
221}
222
223#[cfg(test)]
224mod tests;