chgk_ledb/lib/src/source.rs

207 lines
5.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use serde_derive::{Deserialize, Serialize};
use std::io::{Read, Seek};
use zip::ZipArchive;
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct SourceQuestion {
#[serde(default)]
pub num: u32,
pub id: String,
#[serde(alias = "Вопрос")]
pub description: String,
#[serde(alias = "Ответ")]
pub answer: String,
#[serde(alias = "Автор")]
#[serde(default)]
pub author: String,
#[serde(alias = "Комментарий")]
#[serde(default)]
pub comment: String,
#[serde(alias = "Комментарии")]
#[serde(alias = "Инфо")]
#[serde(default)]
pub comment1: String,
#[serde(alias = "Тур")]
#[serde(default)]
pub tour: String,
#[serde(alias = "Ссылка")]
#[serde(alias = "URL")]
#[serde(default)]
pub url: String,
#[serde(alias = "Дата")]
#[serde(default)]
pub date: String,
#[serde(alias = "Обработан")]
#[serde(default)]
pub processed_by: String,
#[serde(alias = "Редактор")]
#[serde(default)]
pub redacted_by: String,
#[serde(alias = "Копирайт")]
#[serde(default)]
pub copyright: String,
#[serde(alias = "Тема")]
#[serde(default)]
pub theme: String,
#[serde(alias = "Вид")]
#[serde(alias = "Тип")]
#[serde(default)]
pub kind: String,
#[serde(alias = "Источник")]
#[serde(default)]
pub source: String,
#[serde(alias = "Рейтинг")]
#[serde(default)]
pub rating: String,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct SourceQuestionsBatch {
#[serde(default)]
pub filename: String,
#[serde(alias = "Пакет")]
#[serde(alias = "Чемпионат")]
pub description: String,
#[serde(alias = "Автор")]
#[serde(default)]
pub author: String,
#[serde(alias = "Комментарий")]
#[serde(alias = "Комментарии")]
#[serde(alias = "Инфо")]
#[serde(default)]
pub comment: String,
#[serde(alias = "Ссылка")]
#[serde(alias = "URL")]
#[serde(default)]
pub url: String,
#[serde(alias = "Дата")]
#[serde(default)]
pub date: String,
#[serde(alias = "Обработан")]
#[serde(default)]
pub processed_by: String,
#[serde(alias = "Редактор")]
#[serde(default)]
pub redacted_by: String,
#[serde(alias = "Копирайт")]
#[serde(default)]
pub copyright: String,
#[serde(alias = "Тема")]
#[serde(default)]
pub theme: String,
#[serde(alias = "Вид")]
#[serde(alias = "Тип")]
#[serde(default)]
pub kind: String,
#[serde(alias = "Источник")]
#[serde(default)]
pub source: String,
#[serde(alias = "Рейтинг")]
#[serde(default)]
pub rating: String,
#[serde(alias = "Вопросы")]
pub questions: Vec<SourceQuestion>,
}
pub struct SourceQuestionsZipReader<R>
where
R: Read + Seek,
{
zipfile: ZipArchive<R>,
index: Option<usize>,
}
impl<R> SourceQuestionsZipReader<R>
where
R: Read + Seek,
{
fn new(zipfile: ZipArchive<R>) -> Self {
SourceQuestionsZipReader {
zipfile,
index: None,
}
}
}
impl<R> Iterator for SourceQuestionsZipReader<R>
where
R: Read + Seek,
{
type Item = (String, Result<SourceQuestionsBatch, serde_json::Error>);
fn next(&mut self) -> Option<Self::Item> {
if self.index.is_none() && !self.zipfile.is_empty() {
self.index = Some(0);
}
match self.index {
Some(i) if i < self.zipfile.len() => {
self.index = Some(i + 1);
self.nth(i)
}
_ => None,
}
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
if self.zipfile.len() <= n {
return None;
}
self.index = Some(n + 1);
let file = self.zipfile.by_index(n).unwrap();
let name = file.mangled_name();
let name_str = name.to_str().unwrap();
let data: Result<SourceQuestionsBatch, _> = serde_json::from_reader(file);
Some((String::from(name_str), data))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.zipfile.len();
let index = self.index.unwrap_or(0);
let rem = if len > index + 1 {
len - (index + 1)
} else {
0
};
(rem, Some(rem))
}
fn count(self) -> usize
where
Self: Sized,
{
self.zipfile.len()
}
}
impl<R> ExactSizeIterator for SourceQuestionsZipReader<R>
where
R: Read + Seek,
{
fn len(&self) -> usize {
self.zipfile.len()
}
}
pub trait ReadSourceQuestionsBatches<R>
where
R: Read + Seek,
{
fn source_questions(self) -> SourceQuestionsZipReader<R>;
}
impl<R> ReadSourceQuestionsBatches<R> for ZipArchive<R>
where
R: Read + Seek,
{
fn source_questions(self) -> SourceQuestionsZipReader<R> {
SourceQuestionsZipReader::new(self)
}
}