mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-11-10 06:34:18 +00:00
it worked! From dyn Tag into any concrete tag without cloning
This commit is contained in:
parent
e218f6c47d
commit
aa945ae7b6
29 changed files with 150 additions and 123 deletions
64
.github/workflow/main.yml
vendored
Normal file
64
.github/workflow/main.yml
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
on: [push, pull_request]
|
||||
|
||||
name: Continuous integration
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: check
|
||||
|
||||
test:
|
||||
name: Test Suite
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
|
||||
fmt:
|
||||
name: Rustfmt
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- run: rustup component add rustfmt
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --all -- --check
|
||||
|
||||
clippy:
|
||||
name: Clippy
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- run: rustup component add clippy
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: -- -D warnings
|
|
@ -1,3 +1,11 @@
|
|||
## [0.2.718] 2020-10-27
|
||||
|
||||
- downcasting
|
||||
|
||||
## [0.2.71] 2020-10-27
|
||||
|
||||
- Remove use of `Cow`
|
||||
|
||||
## [0.2.5] 2020-10-27
|
||||
|
||||
- Naive implementation of config
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "audiotags"
|
||||
version = "0.2.71"
|
||||
version = "0.2.718"
|
||||
authors = ["Tianyi <ShiTianyi2001@outlook.com>"]
|
||||
edition = "2018"
|
||||
description = "Unified IO for different types of audio metadata"
|
||||
|
@ -14,4 +14,4 @@ id3 = "0.5.1"
|
|||
mp4ameta = "0.6"
|
||||
metaflac = "0.2"
|
||||
thiserror = "1.0.21"
|
||||
audiotags-dev-macro = {path = "./audiotags-dev-macro", version = "0.1.2"}
|
||||
audiotags-dev-macro = {path = "./audiotags-dev-macro", version = "0.1"}
|
BIN
assets/a.mp3
BIN
assets/a.mp3
Binary file not shown.
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "audiotags-dev-macro"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
authors = ["Tianyi <ShiTianyi2001@outlook.com>"]
|
||||
edition = "2018"
|
||||
description = "macros used during the development of audiotags"
|
||||
|
|
|
@ -14,7 +14,7 @@ macro_rules! impl_audiotag_config {
|
|||
|
||||
#[macro_export]
|
||||
macro_rules! impl_tag {
|
||||
($tag:ident , $inner:ident) => {
|
||||
($tag:ident , $inner:ident, $tag_type:expr) => {
|
||||
#[derive(Default)]
|
||||
pub struct $tag {
|
||||
inner: $inner,
|
||||
|
@ -33,13 +33,24 @@ macro_rules! impl_tag {
|
|||
}
|
||||
impl_audiotag_config!($tag);
|
||||
|
||||
use std::any::Any;
|
||||
|
||||
impl IntoAnyTag for $tag {
|
||||
fn into_anytag(&self) -> AnyTag<'_> {
|
||||
self.into()
|
||||
}
|
||||
fn into_any(&self) -> &dyn std::any::Any {
|
||||
fn into_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn into_any_mut(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl $tag {
|
||||
pub(crate) fn into_any_owned(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioTag for $tag {}
|
||||
|
@ -61,23 +72,45 @@ macro_rules! impl_tag {
|
|||
|
||||
// downcasting
|
||||
|
||||
impl<'a> std::convert::TryFrom<&'a Box<dyn AudioTag>> for &'a $tag {
|
||||
type Error = crate::Error;
|
||||
fn try_from(inp: &'a Box<dyn AudioTag>) -> crate::Result<Self> {
|
||||
inp.into_any()
|
||||
.downcast_ref::<$tag>()
|
||||
.ok_or(crate::Error::DowncastError)
|
||||
// impl<'a> std::convert::TryFrom<&'a Box<dyn AudioTag>> for &'a $tag {
|
||||
// type Error = crate::Error;
|
||||
// fn try_from(inp: &'a Box<dyn AudioTag>) -> crate::Result<Self> {
|
||||
// inp.into_any()
|
||||
// .downcast_ref::<$tag>()
|
||||
// .ok_or(crate::Error::DowncastError)
|
||||
// }
|
||||
// }
|
||||
|
||||
impl From<Box<dyn AudioTag>> for $tag {
|
||||
fn from(inp: Box<dyn AudioTag>) -> Self {
|
||||
let mut inp = inp;
|
||||
if let Some(t_refmut) = inp.into_any_mut().downcast_mut::<$tag>() {
|
||||
let t = std::mem::replace(t_refmut, $tag::new()); // TODO: can we avoid creating the dummy tag?
|
||||
t
|
||||
} else {
|
||||
let mut t = inp.into_tag($tag_type);
|
||||
let t_refmut = t.into_any_mut().downcast_mut::<$tag>().unwrap();
|
||||
let t = std::mem::replace(t_refmut, $tag::new());
|
||||
t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<Box<dyn AudioTag>> for $inner {
|
||||
type Error = crate::Error;
|
||||
fn try_from(inp: Box<dyn AudioTag>) -> crate::Result<Self> {
|
||||
let t: &$tag = inp
|
||||
.into_any()
|
||||
.downcast_ref::<$tag>()
|
||||
.ok_or(crate::Error::DowncastError)?;
|
||||
Ok(t.into())
|
||||
// impl std::convert::TryFrom<Box<dyn AudioTag>> for $inner {
|
||||
// type Error = crate::Error;
|
||||
// fn try_from(inp: Box<dyn AudioTag>) -> crate::Result<Self> {
|
||||
// let t: &$tag = inp
|
||||
// .into_any()
|
||||
// .downcast_ref::<$tag>()
|
||||
// .ok_or(crate::Error::DowncastError)?;
|
||||
// Ok(t.into())
|
||||
// }
|
||||
// }
|
||||
|
||||
impl std::convert::From<Box<dyn AudioTag>> for $inner {
|
||||
fn from(inp: Box<dyn AudioTag>) -> Self {
|
||||
let t: $tag = inp.into();
|
||||
(&t).into()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Binary file not shown.
|
@ -1,6 +1,7 @@
|
|||
book_filename: "audiotags"
|
||||
rmd_files: ["index.Rmd", "simple.Rmd", "convert.Rmd", "anytag.Rmd", "downcast.Rmd"]
|
||||
output_dir: "../docs"
|
||||
delete_merged_file: true
|
||||
language:
|
||||
ui:
|
||||
chapter_name: "Chapter "
|
||||
# language:
|
||||
# ui:
|
||||
# chapter_name: "Chapter "
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 21 KiB |
Binary file not shown.
|
@ -21,7 +21,7 @@ fn main() {
|
|||
.expect("Fail to read!");
|
||||
assert_eq!(id3tag_reload.title(), Some("title from metaflac::Tag"));
|
||||
|
||||
let mut id3tag_inner: id3::Tag = id3tag_reload.try_into().unwrap();
|
||||
let mut id3tag_inner: id3::Tag = id3tag_reload.into();
|
||||
// this would fail if `id3tag_reload` isn't really a id3 tag.
|
||||
|
||||
let timestamp = id3::Timestamp {
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -4,7 +4,7 @@ author: "Tianyi Shi"
|
|||
date: "`r Sys.Date()`"
|
||||
site: bookdown::bookdown_site
|
||||
documentclass: book
|
||||
bibliography: [book.bib, packages.bib]
|
||||
bibliography: [book.bib]
|
||||
biblio-style: apalike
|
||||
link-citations: yes
|
||||
description: "This is the manual of the Rust crate 'audiotags'"
|
||||
|
|
0
rtfm/intro.Rmd
Normal file
0
rtfm/intro.Rmd
Normal file
|
@ -1,85 +0,0 @@
|
|||
@Manual{R-base,
|
||||
title = {R: A Language and Environment for Statistical Computing},
|
||||
author = {{R Core Team}},
|
||||
organization = {R Foundation for Statistical Computing},
|
||||
address = {Vienna, Austria},
|
||||
year = {2020},
|
||||
url = {https://www.R-project.org/},
|
||||
}
|
||||
|
||||
@Manual{R-bookdown,
|
||||
title = {bookdown: Authoring Books and Technical Documents with R Markdown},
|
||||
author = {Yihui Xie},
|
||||
year = {2020},
|
||||
note = {R package version 0.21},
|
||||
url = {https://github.com/rstudio/bookdown},
|
||||
}
|
||||
|
||||
@Manual{R-knitr,
|
||||
title = {knitr: A General-Purpose Package for Dynamic Report Generation in R},
|
||||
author = {Yihui Xie},
|
||||
year = {2020},
|
||||
note = {R package version 1.30},
|
||||
url = {https://yihui.org/knitr/},
|
||||
}
|
||||
|
||||
@Manual{R-rmarkdown,
|
||||
title = {rmarkdown: Dynamic Documents for R},
|
||||
author = {JJ Allaire and Yihui Xie and Jonathan McPherson and Javier Luraschi and Kevin Ushey and Aron Atkins and Hadley Wickham and Joe Cheng and Winston Chang and Richard Iannone},
|
||||
year = {2020},
|
||||
note = {R package version 2.4},
|
||||
url = {https://github.com/rstudio/rmarkdown},
|
||||
}
|
||||
|
||||
@Book{bookdown2016,
|
||||
title = {bookdown: Authoring Books and Technical Documents with {R} Markdown},
|
||||
author = {Yihui Xie},
|
||||
publisher = {Chapman and Hall/CRC},
|
||||
address = {Boca Raton, Florida},
|
||||
year = {2016},
|
||||
note = {ISBN 978-1138700109},
|
||||
url = {https://github.com/rstudio/bookdown},
|
||||
}
|
||||
|
||||
@Book{knitr2015,
|
||||
title = {Dynamic Documents with {R} and knitr},
|
||||
author = {Yihui Xie},
|
||||
publisher = {Chapman and Hall/CRC},
|
||||
address = {Boca Raton, Florida},
|
||||
year = {2015},
|
||||
edition = {2nd},
|
||||
note = {ISBN 978-1498716963},
|
||||
url = {https://yihui.org/knitr/},
|
||||
}
|
||||
|
||||
@InCollection{knitr2014,
|
||||
booktitle = {Implementing Reproducible Computational Research},
|
||||
editor = {Victoria Stodden and Friedrich Leisch and Roger D. Peng},
|
||||
title = {knitr: A Comprehensive Tool for Reproducible Research in {R}},
|
||||
author = {Yihui Xie},
|
||||
publisher = {Chapman and Hall/CRC},
|
||||
year = {2014},
|
||||
note = {ISBN 978-1466561595},
|
||||
url = {http://www.crcpress.com/product/isbn/9781466561595},
|
||||
}
|
||||
|
||||
@Book{rmarkdown2018,
|
||||
title = {R Markdown: The Definitive Guide},
|
||||
author = {Yihui Xie and J.J. Allaire and Garrett Grolemund},
|
||||
publisher = {Chapman and Hall/CRC},
|
||||
address = {Boca Raton, Florida},
|
||||
year = {2018},
|
||||
note = {ISBN 9781138359338},
|
||||
url = {https://bookdown.org/yihui/rmarkdown},
|
||||
}
|
||||
|
||||
@Book{rmarkdown2020,
|
||||
title = {R Markdown Cookbook},
|
||||
author = {Yihui Xie and Christophe Dervieux and Emily Riederer},
|
||||
publisher = {Chapman and Hall/CRC},
|
||||
address = {Boca Raton, Florida},
|
||||
year = {2020},
|
||||
note = {ISBN 9780367563837},
|
||||
url = {https://bookdown.org/yihui/rmarkdown-cookbook},
|
||||
}
|
||||
|
|
@ -14,15 +14,6 @@ pre code {
|
|||
}
|
||||
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: 'Merriweather';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Merriweather'), local('Merriweather-Regular'),
|
||||
url('https://tianyishi2001.github.io/ox/fonts/merriweather-v13-latin-regular.woff2') format('woff2'),
|
||||
url('https://tianyishi2001.github.io/ox/fonts/merriweather-v13-latin-regular.woff') format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-style: normal;
|
||||
|
|
|
@ -3,7 +3,7 @@ use metaflac;
|
|||
|
||||
pub use metaflac::Tag as FlacInnerTag;
|
||||
|
||||
impl_tag!(FlacTag, FlacInnerTag);
|
||||
impl_tag!(FlacTag, FlacInnerTag, TagType::Flac);
|
||||
|
||||
impl<'a> From<AnyTag<'a>> for FlacTag {
|
||||
fn from(inp: AnyTag<'a>) -> Self {
|
||||
|
|
|
@ -3,7 +3,7 @@ use id3;
|
|||
|
||||
pub use id3::Tag as Id3v2InnerTag;
|
||||
|
||||
impl_tag!(Id3v2Tag, Id3v2InnerTag);
|
||||
impl_tag!(Id3v2Tag, Id3v2InnerTag, TagType::Id3v2);
|
||||
|
||||
impl<'a> From<&'a Id3v2Tag> for AnyTag<'a> {
|
||||
fn from(inp: &'a Id3v2Tag) -> Self {
|
||||
|
|
|
@ -3,7 +3,7 @@ use mp4ameta;
|
|||
|
||||
pub use mp4ameta::Tag as Mp4InnerTag;
|
||||
|
||||
impl_tag!(Mp4Tag, Mp4InnerTag);
|
||||
impl_tag!(Mp4Tag, Mp4InnerTag, TagType::Mp4);
|
||||
|
||||
impl<'a> From<&'a Mp4Tag> for AnyTag<'a> {
|
||||
fn from(inp: &'a Mp4Tag) -> Self {
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
//! struct. However, this is going to be a lot of work. I might be able to implement them, but it will be no
|
||||
//! sooner than the Christmas vacation.
|
||||
//!
|
||||
//! See [README](https://github.com/TianyiShi2001/audiotags) for some examples.
|
||||
//! Read the [manual](https://tianyishi2001.github.io/audiotags) for some examples.
|
||||
|
||||
pub(crate) use audiotags_dev_macro::*;
|
||||
|
||||
|
|
|
@ -151,4 +151,18 @@ pub trait IntoAnyTag {
|
|||
}
|
||||
}
|
||||
fn into_any(&self) -> &dyn std::any::Any;
|
||||
fn into_any_mut(&mut self) -> &mut dyn std::any::Any;
|
||||
}
|
||||
|
||||
// struct BoxedAudioTagWrapper {
|
||||
// inner: Box<dyn AudioTag>,
|
||||
// }
|
||||
|
||||
// impl<'a> BoxedAudioTagWrapper {
|
||||
// fn into_tag<T>(self) -> T
|
||||
// where
|
||||
// T: From<AnyTag<'a>>,
|
||||
// {
|
||||
// self.inner.into_anytag().into()
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -17,7 +17,8 @@ fn test_inner() {
|
|||
.expect("Fail to read!");
|
||||
assert_eq!(id3tag_reload.title(), Some("title from metaflac::Tag"));
|
||||
|
||||
let mut id3tag_inner: id3::Tag = id3tag_reload.try_into().unwrap();
|
||||
// let id3tag: Id3v2Tag = id3tag_reload.into();
|
||||
let mut id3tag_inner: id3::Tag = id3tag_reload.into();
|
||||
let timestamp = id3::Timestamp {
|
||||
year: 2013,
|
||||
month: Some(2u8),
|
||||
|
|
Loading…
Reference in a new issue