Skip to content

Commit 20290bb

Browse files
committed
feat: sea_orm support for TorrentFile
1 parent b39c0ab commit 20290bb

File tree

3 files changed

+159
-1
lines changed

3 files changed

+159
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- the `sea_orm` crate feature allows to use `MagnetLink`, `TorrentFile` and `TorrentID`
13+
in sea_orm models
1214
- `TorrentFile`, `DecodedTorrent` and `DecodedInfo` implement `PartialEq`
1315

1416
## Version 0.4.0 (2025-11-10)

src/torrent_file.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use bt_bencode::Value as BencodeValue;
22
use rustc_hex::ToHex;
3+
#[cfg(feature = "sea_orm")]
4+
use sea_orm::prelude::*;
35
use serde::{Deserialize, Serialize};
46
use sha1::{Digest, Sha1};
57

@@ -330,6 +332,61 @@ impl TorrentFile {
330332
}
331333
}
332334

335+
#[cfg(feature = "sea_orm")]
336+
impl From<TorrentFile> for sea_orm::sea_query::Value {
337+
fn from(t: TorrentFile) -> Self {
338+
Value::Bytes(Some(t.to_vec()))
339+
}
340+
}
341+
342+
#[cfg(feature = "sea_orm")]
343+
impl sea_orm::TryGetable for TorrentFile {
344+
fn try_get_by<I: sea_orm::ColIdx>(
345+
res: &sea_orm::QueryResult,
346+
index: I,
347+
) -> Result<Self, sea_orm::error::TryGetError> {
348+
let val: Vec<u8> = res.try_get_by(index)?;
349+
TorrentFile::from_slice(&val).map_err(|e| {
350+
sea_orm::error::TryGetError::DbErr(sea_orm::DbErr::TryIntoErr {
351+
from: "Bytes",
352+
into: "TorrentFile",
353+
source: std::sync::Arc::new(e),
354+
})
355+
})
356+
}
357+
}
358+
359+
#[cfg(feature = "sea_orm")]
360+
impl sea_orm::sea_query::ValueType for TorrentFile {
361+
fn try_from(v: sea_orm::Value) -> Result<Self, sea_orm::sea_query::ValueTypeErr> {
362+
match v {
363+
sea_orm::Value::Bytes(Some(s)) => {
364+
TorrentFile::from_slice(&s).map_err(|_e| sea_orm::sea_query::ValueTypeErr)
365+
}
366+
_ => Err(sea_orm::sea_query::ValueTypeErr),
367+
}
368+
}
369+
370+
fn type_name() -> String {
371+
"TorrentFile".to_string()
372+
}
373+
374+
fn array_type() -> sea_orm::sea_query::ArrayType {
375+
sea_orm::sea_query::ArrayType::Bytes
376+
}
377+
378+
fn column_type() -> sea_orm::sea_query::ColumnType {
379+
sea_orm::sea_query::ColumnType::VarBinary(StringLen::None)
380+
}
381+
}
382+
383+
#[cfg(feature = "sea_orm")]
384+
impl sea_orm::sea_query::Nullable for TorrentFile {
385+
fn null() -> sea_orm::sea_query::Value {
386+
sea_orm::sea_query::Value::Bytes(None)
387+
}
388+
}
389+
333390
#[cfg(test)]
334391
mod tests {
335392
use super::*;

tests/sea_orm.rs

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use hightorrent::{MagnetLink, TorrentID};
1+
use hightorrent::{MagnetLink, TorrentFile, TorrentID};
22
use sea_orm::entity::prelude::*;
33
use sea_orm::*;
44

@@ -465,3 +465,102 @@ async fn test_torrent_real_optional_notset() {
465465
assert_eq!(saved_model.magnet.as_ref(), None);
466466
assert_eq!(nonactive_model.magnet.as_ref(), None);
467467
}
468+
469+
#[tokio::test]
470+
async fn test_torrent_real_db() {
471+
use sea_orm_migration::*;
472+
473+
let tmpdir = async_tempfile::TempDir::new().await.unwrap();
474+
let sqlite = tmpdir.join("mixed.sqlite");
475+
let sqlite_str = sqlite.to_str().unwrap();
476+
477+
let db = sea_orm::Database::connect(&format!("sqlite://{}?mode=rwc", sqlite_str))
478+
.await
479+
.unwrap();
480+
mixed_torrent::Migrator::up(&db, None).await.unwrap();
481+
482+
let torrent =
483+
TorrentFile::from_slice(&std::fs::read("tests/bittorrent-v2-test.torrent").unwrap())
484+
.unwrap();
485+
486+
let model = mixed_torrent::ActiveModel {
487+
torrent_id: Set(torrent.id()),
488+
torrent_file: Set(torrent.clone()),
489+
..Default::default()
490+
}
491+
.save(&db)
492+
.await
493+
.unwrap();
494+
495+
let torrent2 =
496+
TorrentFile::from_slice(&std::fs::read("tests/bittorrent-v2-hybrid-test.torrent").unwrap())
497+
.unwrap();
498+
499+
let model2 = mixed_torrent::ActiveModel {
500+
torrent_id: Set(torrent2.id()),
501+
torrent_file: Set(torrent2.clone()),
502+
..Default::default()
503+
}
504+
.save(&db)
505+
.await
506+
.unwrap();
507+
508+
let nonactive_model = model.try_into_model().unwrap();
509+
let saved_model_by_id = mixed_torrent::Entity::find_by_id(nonactive_model.id)
510+
.one(&db)
511+
.await
512+
.unwrap()
513+
.unwrap();
514+
assert_eq!(saved_model_by_id, nonactive_model);
515+
assert_eq!(saved_model_by_id.torrent_file, torrent);
516+
assert_eq!(nonactive_model.torrent_file, torrent);
517+
518+
let nonactive_model2 = model2.try_into_model().unwrap();
519+
let saved_model_by_id2 = mixed_torrent::Entity::find_by_id(nonactive_model2.id)
520+
.one(&db)
521+
.await
522+
.unwrap()
523+
.unwrap();
524+
assert_eq!(saved_model_by_id2, nonactive_model2);
525+
assert_eq!(saved_model_by_id2.torrent_file, torrent2);
526+
assert_eq!(nonactive_model2.torrent_file, torrent2);
527+
528+
// Try query by TorrentID
529+
let saved_model_by_torrentid = mixed_torrent::Entity::find()
530+
.filter(mixed_torrent::Column::TorrentId.eq(torrent.id()))
531+
.one(&db)
532+
.await
533+
.unwrap()
534+
.unwrap();
535+
assert_eq!(saved_model_by_id, nonactive_model);
536+
assert_eq!(saved_model_by_torrentid.torrent_file, torrent);
537+
538+
// Try query by TorrentFile
539+
let saved_model_by_torrent = mixed_torrent::Entity::find()
540+
.filter(mixed_torrent::Column::TorrentFile.eq(torrent.clone()))
541+
.one(&db)
542+
.await
543+
.unwrap()
544+
.unwrap();
545+
assert_eq!(saved_model_by_id, nonactive_model);
546+
assert_eq!(saved_model_by_torrent.torrent_file, torrent);
547+
548+
// Try listing torrents
549+
let mut found_one = false;
550+
let mut found_two = false;
551+
let list = mixed_torrent::Entity::find().all(&db).await.unwrap();
552+
println!("{:?}", list);
553+
for entry in list {
554+
if entry.torrent_file == torrent && entry.torrent_id == torrent.id() {
555+
found_one = true;
556+
continue;
557+
}
558+
559+
if entry.torrent_file == torrent2 && entry.torrent_id == torrent2.id() {
560+
found_two = true;
561+
}
562+
}
563+
564+
assert!(found_one);
565+
assert!(found_two);
566+
}

0 commit comments

Comments
 (0)