mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-12 13:42:34 +00:00
0.2.7182
This commit is contained in:
parent
aa945ae7b6
commit
1206194d5f
26 changed files with 735 additions and 316 deletions
|
@ -1,3 +1,8 @@
|
|||
## [0.2.7182] 2020-10-29
|
||||
|
||||
- Improve docs
|
||||
- Ergonomic conversions
|
||||
|
||||
## [0.2.718] 2020-10-27
|
||||
|
||||
- downcasting
|
||||
|
|
|
@ -14,4 +14,8 @@ id3 = "0.5.1"
|
|||
mp4ameta = "0.6"
|
||||
metaflac = "0.2"
|
||||
thiserror = "1.0.21"
|
||||
audiotags-dev-macro = {path = "./audiotags-dev-macro", version = "0.1"}
|
||||
audiotags-dev-macro = {path = "./audiotags-dev-macro", version = "0.1"}
|
||||
|
||||
[features]
|
||||
defualt = ['from']
|
||||
from = []
|
BIN
assets/a.mp3
BIN
assets/a.mp3
Binary file not shown.
|
@ -35,32 +35,31 @@ macro_rules! impl_tag {
|
|||
|
||||
use std::any::Any;
|
||||
|
||||
impl IntoAnyTag for $tag {
|
||||
fn into_anytag(&self) -> AnyTag<'_> {
|
||||
impl ToAnyTag for $tag {
|
||||
fn to_anytag(&self) -> AnyTag<'_> {
|
||||
self.into()
|
||||
}
|
||||
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 ToAny for $tag {
|
||||
fn to_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any_mut(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioTag for $tag {}
|
||||
|
||||
impl From<&$tag> for $inner {
|
||||
fn from(inp: &$tag) -> Self {
|
||||
inp.inner.clone()
|
||||
// From wrapper to inner (same type)
|
||||
impl From<$tag> for $inner {
|
||||
fn from(inp: $tag) -> Self {
|
||||
inp.inner
|
||||
}
|
||||
}
|
||||
|
||||
// From inner to wrapper (same type)
|
||||
impl From<$inner> for $tag {
|
||||
fn from(inp: $inner) -> Self {
|
||||
Self {
|
||||
|
@ -70,47 +69,26 @@ 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)
|
||||
// }
|
||||
// }
|
||||
|
||||
// From dyn AudioTag to wrapper (any type)
|
||||
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>() {
|
||||
if let Some(t_refmut) = inp.to_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 mut t = inp.to_dyn_tag($tag_type);
|
||||
let t_refmut = t.to_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())
|
||||
// }
|
||||
// }
|
||||
|
||||
// From dyn AudioTag to inner (any type)
|
||||
impl std::convert::From<Box<dyn AudioTag>> for $inner {
|
||||
fn from(inp: Box<dyn AudioTag>) -> Self {
|
||||
let t: $tag = inp.into();
|
||||
(&t).into()
|
||||
t.into()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Chapter 3 AnyTag | audiotags Manual</title>
|
||||
<title>3 AnyTag | audiotags Manual</title>
|
||||
<meta name="description" content="This is the manual of the Rust crate ‘audiotags’" />
|
||||
<meta name="generator" content="bookdown 0.21 and GitBook 2.6.7" />
|
||||
|
||||
<meta property="og:title" content="Chapter 3 AnyTag | audiotags Manual" />
|
||||
<meta property="og:title" content="3 AnyTag | audiotags Manual" />
|
||||
<meta property="og:type" content="book" />
|
||||
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
|||
|
||||
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:title" content="Chapter 3 AnyTag | audiotags Manual" />
|
||||
<meta name="twitter:title" content="3 AnyTag | audiotags Manual" />
|
||||
|
||||
<meta name="twitter:description" content="This is the manual of the Rust crate ‘audiotags’" />
|
||||
|
||||
|
@ -24,15 +24,15 @@
|
|||
<meta name="author" content="Tianyi Shi" />
|
||||
|
||||
|
||||
<meta name="date" content="2020-10-27" />
|
||||
<meta name="date" content="2020-10-29" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
|
||||
|
||||
<link rel="prev" href="conversion.html"/>
|
||||
<link rel="next" href="downcast.html"/>
|
||||
<link rel="prev" href="conversion-and-downcast.html"/>
|
||||
|
||||
<script src="libs/header-attrs-2.4/header-attrs.js"></script>
|
||||
<script src="libs/jquery-2.2.3/jquery.min.js"></script>
|
||||
<link href="libs/gitbook-2.6.7/css/style.css" rel="stylesheet" />
|
||||
|
@ -138,10 +138,13 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
|
|||
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#examples-in-this-manual"><i class="fa fa-check"></i>Examples in this manual</a></li>
|
||||
</ul></li>
|
||||
<li class="chapter" data-level="1" data-path="start-simple.html"><a href="start-simple.html"><i class="fa fa-check"></i><b>1</b> Start Simple</a></li>
|
||||
<li class="chapter" data-level="2" data-path="conversion.html"><a href="conversion.html"><i class="fa fa-check"></i><b>2</b> Conversion</a></li>
|
||||
<li class="chapter" data-level="2" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html"><i class="fa fa-check"></i><b>2</b> Conversion and Downcast</a>
|
||||
<ul>
|
||||
<li class="chapter" data-level="2.1" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html#converting-from-a-boxdyn-audiotag-to-another"><i class="fa fa-check"></i><b>2.1</b> Converting from a <code>Box<dyn AudioTag</code> to Another</a></li>
|
||||
<li class="chapter" data-level="2.2" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html#converting-into-a-concrete-type-downcasting"><i class="fa fa-check"></i><b>2.2</b> Converting into a Concrete Type (Downcasting)</a></li>
|
||||
<li class="chapter" data-level="2.3" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html#upcasting"><i class="fa fa-check"></i><b>2.3</b> Upcasting</a></li>
|
||||
</ul></li>
|
||||
<li class="chapter" data-level="3" data-path="anytag.html"><a href="anytag.html"><i class="fa fa-check"></i><b>3</b> <code>AnyTag</code></a></li>
|
||||
<li class="chapter" data-level="4" data-path="downcast.html"><a href="downcast.html"><i class="fa fa-check"></i><b>4</b> Downcast</a></li>
|
||||
<li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>References</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li>
|
||||
|
||||
|
@ -163,18 +166,18 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
|
|||
|
||||
<section class="normal" id="section-">
|
||||
<div id="anytag" class="section level1" number="3">
|
||||
<h1><span class="header-section-number">Chapter 3</span> <code>AnyTag</code></h1>
|
||||
<h1><span class="header-section-number">3</span> <code>AnyTag</code></h1>
|
||||
<p>The following example shows how you can create a “generic” <code>AnyTag</code> and convert it into a specific tag type.</p>
|
||||
<div class="sourceCode" id="cb3"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb3-1"><a href="anytag.html#cb3-1" aria-hidden="true"></a><span class="kw">use</span> <span class="pp">audiotags::</span><span class="op">{</span>AnyTag<span class="op">,</span> AudioTagEdit<span class="op">,</span> Id3v2Tag<span class="op">};</span></span>
|
||||
<span id="cb3-2"><a href="anytag.html#cb3-2" aria-hidden="true"></a></span>
|
||||
<span id="cb3-3"><a href="anytag.html#cb3-3" aria-hidden="true"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
|
||||
<span id="cb3-4"><a href="anytag.html#cb3-4" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> tag <span class="op">=</span> <span class="pp">AnyTag::</span><span class="kw">default</span>()<span class="op">;</span></span>
|
||||
<span id="cb3-5"><a href="anytag.html#cb3-5" aria-hidden="true"></a> tag<span class="op">.</span>set_title(<span class="st">"foo"</span>)<span class="op">;</span></span>
|
||||
<span id="cb3-6"><a href="anytag.html#cb3-6" aria-hidden="true"></a> tag<span class="op">.</span>set_year(<span class="dv">2001</span>)<span class="op">;</span></span>
|
||||
<span id="cb3-7"><a href="anytag.html#cb3-7" aria-hidden="true"></a> <span class="kw">let</span> tag<span class="op">:</span> Id3v2Tag <span class="op">=</span> tag<span class="op">.</span>into()<span class="op">;</span></span>
|
||||
<span id="cb3-8"><a href="anytag.html#cb3-8" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(tag<span class="op">.</span>year()<span class="op">,</span> <span class="cn">Some</span>(<span class="dv">2001</span>))<span class="op">;</span></span>
|
||||
<span id="cb3-9"><a href="anytag.html#cb3-9" aria-hidden="true"></a> tag<span class="op">.</span>write_to_path(<span class="st">"assets/a.mp3"</span>)<span class="op">.</span>unwrap()<span class="op">;</span></span>
|
||||
<span id="cb3-10"><a href="anytag.html#cb3-10" aria-hidden="true"></a><span class="op">}</span></span></code></pre></div>
|
||||
<div class="sourceCode" id="cb7"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb7-1"><a href="anytag.html#cb7-1" aria-hidden="true"></a><span class="kw">use</span> <span class="pp">audiotags::</span><span class="op">{</span>AnyTag<span class="op">,</span> AudioTagEdit<span class="op">,</span> Id3v2Tag<span class="op">};</span></span>
|
||||
<span id="cb7-2"><a href="anytag.html#cb7-2" aria-hidden="true"></a></span>
|
||||
<span id="cb7-3"><a href="anytag.html#cb7-3" aria-hidden="true"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
|
||||
<span id="cb7-4"><a href="anytag.html#cb7-4" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> tag <span class="op">=</span> <span class="pp">AnyTag::</span><span class="kw">default</span>()<span class="op">;</span></span>
|
||||
<span id="cb7-5"><a href="anytag.html#cb7-5" aria-hidden="true"></a> tag<span class="op">.</span>set_title(<span class="st">"foo"</span>)<span class="op">;</span></span>
|
||||
<span id="cb7-6"><a href="anytag.html#cb7-6" aria-hidden="true"></a> tag<span class="op">.</span>set_year(<span class="dv">2001</span>)<span class="op">;</span></span>
|
||||
<span id="cb7-7"><a href="anytag.html#cb7-7" aria-hidden="true"></a> <span class="kw">let</span> tag<span class="op">:</span> Id3v2Tag <span class="op">=</span> tag<span class="op">.</span>into()<span class="op">;</span></span>
|
||||
<span id="cb7-8"><a href="anytag.html#cb7-8" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(tag<span class="op">.</span>year()<span class="op">,</span> <span class="cn">Some</span>(<span class="dv">2001</span>))<span class="op">;</span></span>
|
||||
<span id="cb7-9"><a href="anytag.html#cb7-9" aria-hidden="true"></a> tag<span class="op">.</span>write_to_path(<span class="st">"assets/a.mp3"</span>)<span class="op">.</span>unwrap()<span class="op">;</span></span>
|
||||
<span id="cb7-10"><a href="anytag.html#cb7-10" aria-hidden="true"></a><span class="op">}</span></span></code></pre></div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
@ -182,8 +185,8 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="conversion.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
|
||||
<a href="downcast.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
|
||||
<a href="conversion-and-downcast.html" class="navigation navigation-prev navigation-unique" aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script src="libs/gitbook-2.6.7/js/app.min.js"></script>
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -116,7 +116,7 @@
|
|||
|
||||
\title{audiotags Manual}
|
||||
\author{Tianyi Shi}
|
||||
\date{2020-10-27}
|
||||
\date{2020-10-29}
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
|
@ -155,16 +155,13 @@ The following example shows how you can read an audio file, parse, set, and save
|
|||
|
||||
\begin{Shaded}
|
||||
\begin{Highlighting}[]
|
||||
\KeywordTok{use} \PreprocessorTok{audiotags::}\OperatorTok{\{}\NormalTok{MimeType}\OperatorTok{,}\NormalTok{ Picture}\OperatorTok{,}\NormalTok{ Tag}\OperatorTok{,}\NormalTok{ TagType}\OperatorTok{\};}
|
||||
|
||||
\KeywordTok{const}\NormalTok{ MP3\_FILE}\OperatorTok{:} \OperatorTok{\&}\OtherTok{\textquotesingle{}static} \DataTypeTok{str} \OperatorTok{=} \StringTok{"assets/a.mp3"}\OperatorTok{;}
|
||||
|
||||
\KeywordTok{fn}\NormalTok{ main() }\OperatorTok{\{}
|
||||
\CommentTok{// using \textasciigrave{}default()\textasciigrave{} so that the metadata format is guessed}
|
||||
\CommentTok{// (from the file extension) (in this case, Id3v2 tag is read)}
|
||||
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ tag }\OperatorTok{=} \PreprocessorTok{Tag::}\KeywordTok{default}\NormalTok{()}\OperatorTok{.}\NormalTok{read\_from\_path(MP3\_FILE)}\OperatorTok{.}\NormalTok{unwrap()}\OperatorTok{;}
|
||||
\CommentTok{// using \textasciigrave{}default()\textasciigrave{} or \textasciigrave{}new()\textasciigrave{} alone so that the metadata format is}
|
||||
\CommentTok{// guessed (from the file extension) (in this case, Id3v2 tag is read)}
|
||||
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ tag }\OperatorTok{=} \PreprocessorTok{Tag::}\NormalTok{new()}\OperatorTok{.}\NormalTok{read\_from\_path(MP3\_FILE)}\OperatorTok{.}\NormalTok{unwrap()}\OperatorTok{;}
|
||||
\CommentTok{// You can also specify the metadata format (tag type):}
|
||||
\KeywordTok{let}\NormalTok{ \_tag }\OperatorTok{=} \PreprocessorTok{Tag::}\NormalTok{with\_tag\_type(}\PreprocessorTok{TagType::}\NormalTok{Id3v2)}
|
||||
\KeywordTok{let}\NormalTok{ \_tag }\OperatorTok{=} \PreprocessorTok{Tag::}\NormalTok{new()}
|
||||
\OperatorTok{.}\NormalTok{with\_tag\_type(}\PreprocessorTok{TagType::}\NormalTok{Id3v2)}
|
||||
\OperatorTok{.}\NormalTok{read\_from\_path(MP3\_FILE)}
|
||||
\OperatorTok{.}\NormalTok{expect(}\StringTok{"Fail to read!"}\NormalTok{)}\OperatorTok{;}
|
||||
|
||||
|
@ -186,19 +183,45 @@ The following example shows how you can read an audio file, parse, set, and save
|
|||
\PreprocessorTok{assert!}\NormalTok{(tag}\OperatorTok{.}\NormalTok{album\_cover()}\OperatorTok{.}\NormalTok{is\_none())}\OperatorTok{;}
|
||||
\NormalTok{ tag}\OperatorTok{.}\NormalTok{remove\_album\_cover()}\OperatorTok{;}
|
||||
|
||||
\NormalTok{ tag}\OperatorTok{.}\NormalTok{save\_to\_path(MP3\_FILE)}\OperatorTok{.}\NormalTok{expect(}\StringTok{"Fail to save"}\NormalTok{)}\OperatorTok{;}
|
||||
\NormalTok{ tag}\OperatorTok{.}\NormalTok{write\_to\_path(MP3\_FILE)}\OperatorTok{.}\NormalTok{expect(}\StringTok{"Fail to save"}\NormalTok{)}\OperatorTok{;}
|
||||
\CommentTok{// }\AlertTok{TASK}\CommentTok{: reload the file and prove the data have been saved}
|
||||
\OperatorTok{\}}
|
||||
\end{Highlighting}
|
||||
\end{Shaded}
|
||||
|
||||
\hypertarget{conversion}{%
|
||||
\chapter{Conversion}\label{conversion}}
|
||||
|
||||
The following example shows how you can read the tag in an \texttt{mp3} file, convert it into an \texttt{mp4} tag, and write it to an \texttt{m4a} file.
|
||||
Note that \texttt{Tag} always reads into a \texttt{Box\textless{}dyn\ AudioTag\textgreater{}}. If you do not want a trait object, you can use the underlying concrete types. However, you'll also need to manually bring the traits into scope if you prefer not to write \texttt{audiotags::*}.
|
||||
|
||||
\begin{Shaded}
|
||||
\begin{Highlighting}[]
|
||||
\KeywordTok{use} \PreprocessorTok{audiotags::}\OperatorTok{\{}\PreprocessorTok{traits::}\OperatorTok{*,}\NormalTok{ FlacTag}\OperatorTok{,}\NormalTok{ Id3v2Tag}\OperatorTok{,}\NormalTok{ Mp4Tag}\OperatorTok{\};}
|
||||
\CommentTok{// or alternatively \textasciigrave{}use audiotags::*\textasciigrave{}}
|
||||
|
||||
\KeywordTok{fn}\NormalTok{ main() }\OperatorTok{\{}
|
||||
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ tag }\OperatorTok{=} \PreprocessorTok{FlacTag::}\NormalTok{read\_from\_path(}\StringTok{"assets/a.flac"}\NormalTok{)}\OperatorTok{.}\NormalTok{unwrap()}\OperatorTok{;}
|
||||
\NormalTok{ tag}\OperatorTok{.}\NormalTok{set\_title(}\StringTok{"foo"}\NormalTok{)}\OperatorTok{;}
|
||||
\PreprocessorTok{assert\_eq!}\NormalTok{(tag}\OperatorTok{.}\NormalTok{title()}\OperatorTok{,} \ConstantTok{Some}\NormalTok{(}\StringTok{"foo"}\NormalTok{))}\OperatorTok{;}
|
||||
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ tag }\OperatorTok{=} \PreprocessorTok{Mp4Tag::}\NormalTok{read\_from\_path(}\StringTok{"assets/a.m4a"}\NormalTok{)}\OperatorTok{.}\NormalTok{unwrap()}\OperatorTok{;}
|
||||
\NormalTok{ tag}\OperatorTok{.}\NormalTok{set\_title(}\StringTok{"foo"}\NormalTok{)}\OperatorTok{;}
|
||||
\PreprocessorTok{assert\_eq!}\NormalTok{(tag}\OperatorTok{.}\NormalTok{title()}\OperatorTok{,} \ConstantTok{Some}\NormalTok{(}\StringTok{"foo"}\NormalTok{))}\OperatorTok{;}
|
||||
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ tag }\OperatorTok{=} \PreprocessorTok{Id3v2Tag::}\NormalTok{read\_from\_path(}\StringTok{"assets/a.mp3"}\NormalTok{)}\OperatorTok{.}\NormalTok{unwrap()}\OperatorTok{;}
|
||||
\NormalTok{ tag}\OperatorTok{.}\NormalTok{set\_title(}\StringTok{"foo"}\NormalTok{)}\OperatorTok{;}
|
||||
\PreprocessorTok{assert\_eq!}\NormalTok{(tag}\OperatorTok{.}\NormalTok{title()}\OperatorTok{,} \ConstantTok{Some}\NormalTok{(}\StringTok{"foo"}\NormalTok{))}\OperatorTok{;}
|
||||
\CommentTok{// all other methods in trait \textasciigrave{}AudioTagEdit\textasciigrave{} are available, not just title}
|
||||
\OperatorTok{\}}
|
||||
\end{Highlighting}
|
||||
\end{Shaded}
|
||||
|
||||
\hypertarget{conversion-and-downcast}{%
|
||||
\chapter{Conversion and Downcast}\label{conversion-and-downcast}}
|
||||
|
||||
The following example shows how you can read the tag in an \texttt{mp3} file, convert it into an \texttt{mp4} tag, and write it to an \texttt{m4a} file.
|
||||
|
||||
\hypertarget{converting-from-a-boxdyn-audiotag-to-another}{%
|
||||
\section{\texorpdfstring{Converting from a \texttt{Box\textless{}dyn\ AudioTag} to Another}{Converting from a Box\textless dyn AudioTag to Another}}\label{converting-from-a-boxdyn-audiotag-to-another}}
|
||||
|
||||
\begin{Shaded}
|
||||
\begin{Highlighting}[]
|
||||
|
||||
\KeywordTok{use} \PreprocessorTok{audiotags::}\OperatorTok{\{}\NormalTok{Config}\OperatorTok{,}\NormalTok{ Tag}\OperatorTok{,}\NormalTok{ TagType}\OperatorTok{\};}
|
||||
|
||||
\KeywordTok{fn}\NormalTok{ main() }\OperatorTok{\{}
|
||||
|
@ -211,12 +234,13 @@ The following example shows how you can read the tag in an \texttt{mp3} file, co
|
|||
\CommentTok{// set the title}
|
||||
\NormalTok{ mp3tag}\OperatorTok{.}\NormalTok{set\_title(}\StringTok{"title from mp3 file"}\NormalTok{)}\OperatorTok{;}
|
||||
\CommentTok{// we can convert it to an mp4 tag and save it to an m4a file.}
|
||||
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ mp4tag }\OperatorTok{=}\NormalTok{ mp3tag}\OperatorTok{.}\NormalTok{into\_tag(}\PreprocessorTok{TagType::}\NormalTok{Mp4)}\OperatorTok{;}
|
||||
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ mp4tag }\OperatorTok{=}\NormalTok{ mp3tag}\OperatorTok{.}\NormalTok{to\_dyn\_tag(}\PreprocessorTok{TagType::}\NormalTok{Mp4)}\OperatorTok{;}
|
||||
\NormalTok{ mp4tag}\OperatorTok{.}\NormalTok{write\_to\_path(M4A\_FILE)}\OperatorTok{.}\NormalTok{unwrap()}\OperatorTok{;}
|
||||
|
||||
\CommentTok{// reload the tag from the m4a file; this time specifying the}
|
||||
\CommentTok{// tag type (you can also use \textasciigrave{}default()\textasciigrave{})}
|
||||
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ mp4tag }\OperatorTok{=} \PreprocessorTok{Tag::}\NormalTok{with\_tag\_type(}\PreprocessorTok{TagType::}\NormalTok{Mp4)}
|
||||
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ mp4tag }\OperatorTok{=} \PreprocessorTok{Tag::}\NormalTok{new()}
|
||||
\OperatorTok{.}\NormalTok{with\_tag\_type(}\PreprocessorTok{TagType::}\NormalTok{Mp4)}
|
||||
\OperatorTok{.}\NormalTok{read\_from\_path(M4A\_FILE)}
|
||||
\OperatorTok{.}\NormalTok{unwrap()}\OperatorTok{;}
|
||||
\CommentTok{// the tag originated from an mp3 file is successfully written}
|
||||
|
@ -232,12 +256,76 @@ The following example shows how you can read the tag in an \texttt{mp3} file, co
|
|||
\CommentTok{// convert to id3 tag, which does not support multiple artists}
|
||||
\NormalTok{ mp4tag}\OperatorTok{.}\NormalTok{set\_config(}\PreprocessorTok{Config::}\KeywordTok{default}\NormalTok{()}\OperatorTok{.}\NormalTok{sep\_artist(}\StringTok{"/"}\NormalTok{))}\OperatorTok{;}
|
||||
\CommentTok{// separator is by default \textasciigrave{};\textasciigrave{} but we can customise it}
|
||||
\KeywordTok{let}\NormalTok{ mp3tag }\OperatorTok{=}\NormalTok{ mp4tag}\OperatorTok{.}\NormalTok{into\_tag(}\PreprocessorTok{TagType::}\NormalTok{Id3v2)}\OperatorTok{;}
|
||||
\KeywordTok{let}\NormalTok{ mp3tag }\OperatorTok{=}\NormalTok{ mp4tag}\OperatorTok{.}\NormalTok{to\_dyn\_tag(}\PreprocessorTok{TagType::}\NormalTok{Id3v2)}\OperatorTok{;}
|
||||
\PreprocessorTok{assert\_eq!}\NormalTok{(mp3tag}\OperatorTok{.}\NormalTok{artist()}\OperatorTok{,} \ConstantTok{Some}\NormalTok{(}\StringTok{"artist1 of mp4/artist2 of mp4"}\NormalTok{))}\OperatorTok{;}
|
||||
\OperatorTok{\}}
|
||||
\end{Highlighting}
|
||||
\end{Shaded}
|
||||
|
||||
\hypertarget{converting-into-a-concrete-type-downcasting}{%
|
||||
\section{Converting into a Concrete Type (Downcasting)}\label{converting-into-a-concrete-type-downcasting}}
|
||||
|
||||
\begin{quote}
|
||||
Can I convert into a concrete type?
|
||||
\end{quote}
|
||||
|
||||
Yes, you can directly convert \texttt{.into()} it (this is technically known as a ``downcast''):
|
||||
|
||||
\begin{Shaded}
|
||||
\begin{Highlighting}[]
|
||||
\KeywordTok{use} \PreprocessorTok{audiotags::}\OperatorTok{\{}\NormalTok{FlacTag}\OperatorTok{,}\NormalTok{ Tag}\OperatorTok{\};}
|
||||
|
||||
\KeywordTok{fn}\NormalTok{ main() }\OperatorTok{\{}
|
||||
\KeywordTok{let}\NormalTok{ id3v2tag }\OperatorTok{=} \PreprocessorTok{Tag::}\KeywordTok{default}\NormalTok{()}\OperatorTok{.}\NormalTok{read\_from\_path(}\StringTok{"assets/a.mp3"}\NormalTok{)}\OperatorTok{.}\NormalTok{unwrap()}\OperatorTok{;}
|
||||
\KeywordTok{let}\NormalTok{ \_flactag}\OperatorTok{:}\NormalTok{ FlacTag }\OperatorTok{=}\NormalTok{ id3v2tag}\OperatorTok{.}\NormalTok{into()}\OperatorTok{;}
|
||||
\CommentTok{// of course, you can \textasciigrave{}let id3v2tag\_concrete: Id3v2Tag = id3v2tag.into();\textasciigrave{}}
|
||||
\OperatorTok{\}}
|
||||
\end{Highlighting}
|
||||
\end{Shaded}
|
||||
|
||||
You can even convert \texttt{.into()} the `backend' tag type:
|
||||
|
||||
\begin{Shaded}
|
||||
\begin{Highlighting}[]
|
||||
\KeywordTok{use} \PreprocessorTok{audiotags::}\NormalTok{Tag}\OperatorTok{;}
|
||||
|
||||
\KeywordTok{fn}\NormalTok{ main() }\OperatorTok{\{}
|
||||
\KeywordTok{let}\NormalTok{ mp3tag }\OperatorTok{=} \PreprocessorTok{Tag::}\KeywordTok{default}\NormalTok{()}\OperatorTok{.}\NormalTok{read\_from\_path(}\StringTok{"assets/a.mp3"}\NormalTok{)}\OperatorTok{.}\NormalTok{unwrap()}\OperatorTok{;}
|
||||
\KeywordTok{let}\NormalTok{ flactag}\OperatorTok{:} \PreprocessorTok{metaflac::}\NormalTok{Tag }\OperatorTok{=}\NormalTok{ mp3tag}\OperatorTok{.}\NormalTok{into()}\OperatorTok{;} \CommentTok{// into the \textquotesingle{}backend\textquotesingle{} tag}
|
||||
\CommentTok{// then you can use methods specific to metaflac}
|
||||
\KeywordTok{let}\NormalTok{ \_ }\OperatorTok{=}\NormalTok{ flactag}\OperatorTok{.}\NormalTok{get\_streaminfo()}\OperatorTok{;}
|
||||
\OperatorTok{\}}
|
||||
\end{Highlighting}
|
||||
\end{Shaded}
|
||||
|
||||
This is useful when you really need to use the methods not provided by \texttt{audiotags::traits::*}.
|
||||
|
||||
You can also downcast the concrete \texttt{audiotags::FlacTag} to \texttt{metaflac::Tag} and so no.
|
||||
|
||||
\hypertarget{upcasting}{%
|
||||
\section{Upcasting}\label{upcasting}}
|
||||
|
||||
Since you're allowed to downcast, naturally you can also upcast:
|
||||
|
||||
\begin{Shaded}
|
||||
\begin{Highlighting}[]
|
||||
\KeywordTok{use} \PreprocessorTok{audiotags::}\OperatorTok{*;}
|
||||
|
||||
\KeywordTok{fn}\NormalTok{ main() }\OperatorTok{\{}
|
||||
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ innertag }\OperatorTok{=} \PreprocessorTok{metaflac::Tag::}\KeywordTok{default}\NormalTok{()}\OperatorTok{;}
|
||||
\NormalTok{ innertag}
|
||||
\OperatorTok{.}\NormalTok{vorbis\_comments\_mut()}
|
||||
\OperatorTok{.}\NormalTok{set\_title(}\PreprocessorTok{vec!}\NormalTok{[}\StringTok{"title from metaflac::Tag"}\NormalTok{])}\OperatorTok{;}
|
||||
\KeywordTok{let}\NormalTok{ tag}\OperatorTok{:}\NormalTok{ FlacTag }\OperatorTok{=}\NormalTok{ innertag}\OperatorTok{.}\NormalTok{into()}\OperatorTok{;}
|
||||
\KeywordTok{let}\NormalTok{ \_id3tag }\OperatorTok{=}\NormalTok{ tag}\OperatorTok{.}\NormalTok{to\_dyn\_tag(}\PreprocessorTok{TagType::}\NormalTok{Id3v2)}\OperatorTok{;}
|
||||
\CommentTok{// in this case the "title" metadata will be}
|
||||
\CommentTok{// losslessly written into the id3tag.}
|
||||
\CommentTok{// However, if you have FLAC{-}specific fields,}
|
||||
\CommentTok{// they will be lost upon conversion}
|
||||
\OperatorTok{\}}
|
||||
\end{Highlighting}
|
||||
\end{Shaded}
|
||||
|
||||
\hypertarget{anytag}{%
|
||||
\chapter{\texorpdfstring{\texttt{AnyTag}}{AnyTag}}\label{anytag}}
|
||||
|
||||
|
@ -258,55 +346,7 @@ The following example shows how you can create a ``generic'' \texttt{AnyTag} and
|
|||
\end{Highlighting}
|
||||
\end{Shaded}
|
||||
|
||||
\hypertarget{downcast}{%
|
||||
\chapter{Downcast}\label{downcast}}
|
||||
|
||||
The following example shows how you can downcast a \texttt{Box\textless{}dyn\ AudioTag\textgreater{}} into its ``backend'' tag type. This allows you to set the uncommon metadata supported by the corresponding backend but not by \textbf{audiotags}.
|
||||
|
||||
\begin{Shaded}
|
||||
\begin{Highlighting}[]
|
||||
\KeywordTok{use} \PreprocessorTok{audiotags::}\OperatorTok{*;}
|
||||
|
||||
\KeywordTok{fn}\NormalTok{ main() }\OperatorTok{\{}
|
||||
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ innertag }\OperatorTok{=} \PreprocessorTok{metaflac::Tag::}\KeywordTok{default}\NormalTok{()}\OperatorTok{;}
|
||||
\NormalTok{ innertag}
|
||||
\OperatorTok{.}\NormalTok{vorbis\_comments\_mut()}
|
||||
\OperatorTok{.}\NormalTok{set\_title(}\PreprocessorTok{vec!}\NormalTok{[}\StringTok{"title from metaflac::Tag"}\NormalTok{])}\OperatorTok{;}
|
||||
\KeywordTok{let}\NormalTok{ tag}\OperatorTok{:}\NormalTok{ FlacTag }\OperatorTok{=}\NormalTok{ innertag}\OperatorTok{.}\NormalTok{into()}\OperatorTok{;}
|
||||
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ id3tag }\OperatorTok{=}\NormalTok{ tag}\OperatorTok{.}\NormalTok{into\_tag(}\PreprocessorTok{TagType::}\NormalTok{Id3v2)}\OperatorTok{;}
|
||||
\NormalTok{ id3tag}
|
||||
\OperatorTok{.}\NormalTok{write\_to\_path(}\StringTok{"assets/a.mp3"}\NormalTok{)}
|
||||
\OperatorTok{.}\NormalTok{expect(}\StringTok{"Fail to write!"}\NormalTok{)}\OperatorTok{;}
|
||||
|
||||
\KeywordTok{let}\NormalTok{ id3tag\_reload }\OperatorTok{=} \PreprocessorTok{Tag::}\KeywordTok{default}\NormalTok{()}
|
||||
\OperatorTok{.}\NormalTok{read\_from\_path(}\StringTok{"assets/a.mp3"}\NormalTok{)}
|
||||
\OperatorTok{.}\NormalTok{expect(}\StringTok{"Fail to read!"}\NormalTok{)}\OperatorTok{;}
|
||||
\PreprocessorTok{assert\_eq!}\NormalTok{(id3tag\_reload}\OperatorTok{.}\NormalTok{title()}\OperatorTok{,} \ConstantTok{Some}\NormalTok{(}\StringTok{"title from metaflac::Tag"}\NormalTok{))}\OperatorTok{;}
|
||||
|
||||
\KeywordTok{let} \KeywordTok{mut}\NormalTok{ id3tag\_inner}\OperatorTok{:} \PreprocessorTok{id3::}\NormalTok{Tag }\OperatorTok{=}\NormalTok{ id3tag\_reload}\OperatorTok{.}\NormalTok{try\_into()}\OperatorTok{.}\NormalTok{unwrap()}\OperatorTok{;}
|
||||
\CommentTok{// this would fail if \textasciigrave{}id3tag\_reload\textasciigrave{} isn\textquotesingle{}t really a id3 tag.}
|
||||
|
||||
\KeywordTok{let}\NormalTok{ timestamp }\OperatorTok{=} \PreprocessorTok{id3::}\NormalTok{Timestamp }\OperatorTok{\{}
|
||||
\NormalTok{ year}\OperatorTok{:} \DecValTok{2013}\OperatorTok{,}
|
||||
\NormalTok{ month}\OperatorTok{:} \ConstantTok{Some}\NormalTok{(}\DecValTok{2u8}\NormalTok{)}\OperatorTok{,}
|
||||
\NormalTok{ day}\OperatorTok{:} \ConstantTok{Some}\NormalTok{(}\DecValTok{5u8}\NormalTok{)}\OperatorTok{,}
|
||||
\NormalTok{ hour}\OperatorTok{:} \ConstantTok{Some}\NormalTok{(}\DecValTok{6u8}\NormalTok{)}\OperatorTok{,}
|
||||
\NormalTok{ minute}\OperatorTok{:} \ConstantTok{None}\OperatorTok{,}
|
||||
\NormalTok{ second}\OperatorTok{:} \ConstantTok{None}\OperatorTok{,}
|
||||
\OperatorTok{\};}
|
||||
\NormalTok{ id3tag\_inner}\OperatorTok{.}\NormalTok{set\_date\_recorded(timestamp}\OperatorTok{.}\NormalTok{clone())}\OperatorTok{;}
|
||||
\NormalTok{ id3tag\_inner}
|
||||
\OperatorTok{.}\NormalTok{write\_to\_path(}\StringTok{"assets/a.mp3"}\OperatorTok{,} \PreprocessorTok{id3::Version::}\NormalTok{Id3v24)}
|
||||
\OperatorTok{.}\NormalTok{expect(}\StringTok{"Fail to write!"}\NormalTok{)}\OperatorTok{;}
|
||||
|
||||
\KeywordTok{let}\NormalTok{ id3tag\_reload }\OperatorTok{=} \PreprocessorTok{id3::Tag::}\NormalTok{read\_from\_path(}\StringTok{"assets/a.mp3"}\NormalTok{)}
|
||||
\OperatorTok{.}\NormalTok{expect(}\StringTok{"Fail to read!"}\NormalTok{)}\OperatorTok{;}
|
||||
\PreprocessorTok{assert\_eq!}\NormalTok{(id3tag\_reload}\OperatorTok{.}\NormalTok{date\_recorded()}\OperatorTok{,} \ConstantTok{Some}\NormalTok{(timestamp))}\OperatorTok{;}
|
||||
\OperatorTok{\}}
|
||||
\end{Highlighting}
|
||||
\end{Shaded}
|
||||
|
||||
|
||||
\bibliography{book.bib,packages.bib}
|
||||
\bibliography{book.bib}
|
||||
|
||||
\end{document}
|
||||
|
|
315
docs/conversion-and-downcast.html
Normal file
315
docs/conversion-and-downcast.html
Normal file
|
@ -0,0 +1,315 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="" xml:lang="">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>2 Conversion and Downcast | audiotags Manual</title>
|
||||
<meta name="description" content="This is the manual of the Rust crate ‘audiotags’" />
|
||||
<meta name="generator" content="bookdown 0.21 and GitBook 2.6.7" />
|
||||
|
||||
<meta property="og:title" content="2 Conversion and Downcast | audiotags Manual" />
|
||||
<meta property="og:type" content="book" />
|
||||
|
||||
|
||||
<meta property="og:description" content="This is the manual of the Rust crate ‘audiotags’" />
|
||||
|
||||
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:title" content="2 Conversion and Downcast | audiotags Manual" />
|
||||
|
||||
<meta name="twitter:description" content="This is the manual of the Rust crate ‘audiotags’" />
|
||||
|
||||
|
||||
<meta name="author" content="Tianyi Shi" />
|
||||
|
||||
|
||||
<meta name="date" content="2020-10-29" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
|
||||
|
||||
<link rel="prev" href="start-simple.html"/>
|
||||
<link rel="next" href="anytag.html"/>
|
||||
<script src="libs/header-attrs-2.4/header-attrs.js"></script>
|
||||
<script src="libs/jquery-2.2.3/jquery.min.js"></script>
|
||||
<link href="libs/gitbook-2.6.7/css/style.css" rel="stylesheet" />
|
||||
<link href="libs/gitbook-2.6.7/css/plugin-table.css" rel="stylesheet" />
|
||||
<link href="libs/gitbook-2.6.7/css/plugin-bookdown.css" rel="stylesheet" />
|
||||
<link href="libs/gitbook-2.6.7/css/plugin-highlight.css" rel="stylesheet" />
|
||||
<link href="libs/gitbook-2.6.7/css/plugin-search.css" rel="stylesheet" />
|
||||
<link href="libs/gitbook-2.6.7/css/plugin-fontsettings.css" rel="stylesheet" />
|
||||
<link href="libs/gitbook-2.6.7/css/plugin-clipboard.css" rel="stylesheet" />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<style type="text/css">
|
||||
pre > code.sourceCode { white-space: pre; position: relative; }
|
||||
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
|
||||
pre > code.sourceCode > span:empty { height: 1.2em; }
|
||||
code.sourceCode > span { color: inherit; text-decoration: inherit; }
|
||||
pre.sourceCode { margin: 0; }
|
||||
@media screen {
|
||||
div.sourceCode { overflow: auto; }
|
||||
}
|
||||
@media print {
|
||||
pre > code.sourceCode { white-space: pre-wrap; }
|
||||
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
|
||||
}
|
||||
pre.numberSource code
|
||||
{ counter-reset: source-line 0; }
|
||||
pre.numberSource code > span
|
||||
{ position: relative; left: -4em; counter-increment: source-line; }
|
||||
pre.numberSource code > span > a:first-child::before
|
||||
{ content: counter(source-line);
|
||||
position: relative; left: -1em; text-align: right; vertical-align: baseline;
|
||||
border: none; display: inline-block;
|
||||
-webkit-touch-callout: none; -webkit-user-select: none;
|
||||
-khtml-user-select: none; -moz-user-select: none;
|
||||
-ms-user-select: none; user-select: none;
|
||||
padding: 0 4px; width: 4em;
|
||||
color: #aaaaaa;
|
||||
}
|
||||
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
|
||||
div.sourceCode
|
||||
{ }
|
||||
@media screen {
|
||||
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
|
||||
}
|
||||
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
|
||||
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
|
||||
code span.at { color: #7d9029; } /* Attribute */
|
||||
code span.bn { color: #40a070; } /* BaseN */
|
||||
code span.bu { } /* BuiltIn */
|
||||
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
|
||||
code span.ch { color: #4070a0; } /* Char */
|
||||
code span.cn { color: #880000; } /* Constant */
|
||||
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
|
||||
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
|
||||
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
|
||||
code span.dt { color: #902000; } /* DataType */
|
||||
code span.dv { color: #40a070; } /* DecVal */
|
||||
code span.er { color: #ff0000; font-weight: bold; } /* Error */
|
||||
code span.ex { } /* Extension */
|
||||
code span.fl { color: #40a070; } /* Float */
|
||||
code span.fu { color: #06287e; } /* Function */
|
||||
code span.im { } /* Import */
|
||||
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
|
||||
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
|
||||
code span.op { color: #666666; } /* Operator */
|
||||
code span.ot { color: #007020; } /* Other */
|
||||
code span.pp { color: #bc7a00; } /* Preprocessor */
|
||||
code span.sc { color: #4070a0; } /* SpecialChar */
|
||||
code span.ss { color: #bb6688; } /* SpecialString */
|
||||
code span.st { color: #4070a0; } /* String */
|
||||
code span.va { color: #19177c; } /* Variable */
|
||||
code span.vs { color: #4070a0; } /* VerbatimString */
|
||||
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
|
||||
</style>
|
||||
|
||||
<link rel="stylesheet" href="style.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<div class="book without-animation with-summary font-size-2 font-family-1" data-basepath=".">
|
||||
|
||||
<div class="book-summary">
|
||||
<nav role="navigation">
|
||||
|
||||
<ul class="summary">
|
||||
<li><strong><a href="https://tianyishi2001.github.io/audiotags">audiotags Manual</a></strong></li>
|
||||
|
||||
<li class="divider"></li>
|
||||
<li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>Preface</a>
|
||||
<ul>
|
||||
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#examples-in-this-manual"><i class="fa fa-check"></i>Examples in this manual</a></li>
|
||||
</ul></li>
|
||||
<li class="chapter" data-level="1" data-path="start-simple.html"><a href="start-simple.html"><i class="fa fa-check"></i><b>1</b> Start Simple</a></li>
|
||||
<li class="chapter" data-level="2" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html"><i class="fa fa-check"></i><b>2</b> Conversion and Downcast</a>
|
||||
<ul>
|
||||
<li class="chapter" data-level="2.1" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html#converting-from-a-boxdyn-audiotag-to-another"><i class="fa fa-check"></i><b>2.1</b> Converting from a <code>Box<dyn AudioTag</code> to Another</a></li>
|
||||
<li class="chapter" data-level="2.2" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html#converting-into-a-concrete-type-downcasting"><i class="fa fa-check"></i><b>2.2</b> Converting into a Concrete Type (Downcasting)</a></li>
|
||||
<li class="chapter" data-level="2.3" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html#upcasting"><i class="fa fa-check"></i><b>2.3</b> Upcasting</a></li>
|
||||
</ul></li>
|
||||
<li class="chapter" data-level="3" data-path="anytag.html"><a href="anytag.html"><i class="fa fa-check"></i><b>3</b> <code>AnyTag</code></a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div class="book-body">
|
||||
<div class="body-inner">
|
||||
<div class="book-header" role="navigation">
|
||||
<h1>
|
||||
<i class="fa fa-circle-o-notch fa-spin"></i><a href="./">audiotags Manual</a>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="page-wrapper" tabindex="-1" role="main">
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-">
|
||||
<div id="conversion-and-downcast" class="section level1" number="2">
|
||||
<h1><span class="header-section-number">2</span> Conversion and Downcast</h1>
|
||||
<p>The following example shows how you can read the tag in an <code>mp3</code> file, convert it into an <code>mp4</code> tag, and write it to an <code>m4a</code> file.</p>
|
||||
<div id="converting-from-a-boxdyn-audiotag-to-another" class="section level2" number="2.1">
|
||||
<h2><span class="header-section-number">2.1</span> Converting from a <code>Box<dyn AudioTag</code> to Another</h2>
|
||||
<div class="sourceCode" id="cb3"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb3-1"><a href="conversion-and-downcast.html#cb3-1" aria-hidden="true"></a></span>
|
||||
<span id="cb3-2"><a href="conversion-and-downcast.html#cb3-2" aria-hidden="true"></a><span class="kw">use</span> <span class="pp">audiotags::</span><span class="op">{</span>Config<span class="op">,</span> Tag<span class="op">,</span> TagType<span class="op">};</span></span>
|
||||
<span id="cb3-3"><a href="conversion-and-downcast.html#cb3-3" aria-hidden="true"></a></span>
|
||||
<span id="cb3-4"><a href="conversion-and-downcast.html#cb3-4" aria-hidden="true"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
|
||||
<span id="cb3-5"><a href="conversion-and-downcast.html#cb3-5" aria-hidden="true"></a> <span class="co">// we have an mp3 and an m4a file</span></span>
|
||||
<span id="cb3-6"><a href="conversion-and-downcast.html#cb3-6" aria-hidden="true"></a> <span class="kw">const</span> MP3_FILE<span class="op">:</span> <span class="op">&</span><span class="ot">'static</span> <span class="dt">str</span> <span class="op">=</span> <span class="st">"assets/a.mp3"</span><span class="op">;</span></span>
|
||||
<span id="cb3-7"><a href="conversion-and-downcast.html#cb3-7" aria-hidden="true"></a> <span class="kw">const</span> M4A_FILE<span class="op">:</span> <span class="op">&</span><span class="ot">'static</span> <span class="dt">str</span> <span class="op">=</span> <span class="st">"assets/a.m4a"</span><span class="op">;</span></span>
|
||||
<span id="cb3-8"><a href="conversion-and-downcast.html#cb3-8" aria-hidden="true"></a> <span class="co">// read tag from the mp3 file. Using `default()` so that the</span></span>
|
||||
<span id="cb3-9"><a href="conversion-and-downcast.html#cb3-9" aria-hidden="true"></a> <span class="co">// type of tag is guessed from the file extension</span></span>
|
||||
<span id="cb3-10"><a href="conversion-and-downcast.html#cb3-10" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> mp3tag <span class="op">=</span> <span class="pp">Tag::</span><span class="kw">default</span>()<span class="op">.</span>read_from_path(MP3_FILE)<span class="op">.</span>unwrap()<span class="op">;</span></span>
|
||||
<span id="cb3-11"><a href="conversion-and-downcast.html#cb3-11" aria-hidden="true"></a> <span class="co">// set the title</span></span>
|
||||
<span id="cb3-12"><a href="conversion-and-downcast.html#cb3-12" aria-hidden="true"></a> mp3tag<span class="op">.</span>set_title(<span class="st">"title from mp3 file"</span>)<span class="op">;</span></span>
|
||||
<span id="cb3-13"><a href="conversion-and-downcast.html#cb3-13" aria-hidden="true"></a> <span class="co">// we can convert it to an mp4 tag and save it to an m4a file.</span></span>
|
||||
<span id="cb3-14"><a href="conversion-and-downcast.html#cb3-14" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> mp4tag <span class="op">=</span> mp3tag<span class="op">.</span>to_dyn_tag(<span class="pp">TagType::</span>Mp4)<span class="op">;</span></span>
|
||||
<span id="cb3-15"><a href="conversion-and-downcast.html#cb3-15" aria-hidden="true"></a> mp4tag<span class="op">.</span>write_to_path(M4A_FILE)<span class="op">.</span>unwrap()<span class="op">;</span></span>
|
||||
<span id="cb3-16"><a href="conversion-and-downcast.html#cb3-16" aria-hidden="true"></a></span>
|
||||
<span id="cb3-17"><a href="conversion-and-downcast.html#cb3-17" aria-hidden="true"></a> <span class="co">// reload the tag from the m4a file; this time specifying the</span></span>
|
||||
<span id="cb3-18"><a href="conversion-and-downcast.html#cb3-18" aria-hidden="true"></a> <span class="co">// tag type (you can also use `default()`)</span></span>
|
||||
<span id="cb3-19"><a href="conversion-and-downcast.html#cb3-19" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> mp4tag <span class="op">=</span> <span class="pp">Tag::</span>new()</span>
|
||||
<span id="cb3-20"><a href="conversion-and-downcast.html#cb3-20" aria-hidden="true"></a> <span class="op">.</span>with_tag_type(<span class="pp">TagType::</span>Mp4)</span>
|
||||
<span id="cb3-21"><a href="conversion-and-downcast.html#cb3-21" aria-hidden="true"></a> <span class="op">.</span>read_from_path(M4A_FILE)</span>
|
||||
<span id="cb3-22"><a href="conversion-and-downcast.html#cb3-22" aria-hidden="true"></a> <span class="op">.</span>unwrap()<span class="op">;</span></span>
|
||||
<span id="cb3-23"><a href="conversion-and-downcast.html#cb3-23" aria-hidden="true"></a> <span class="co">// the tag originated from an mp3 file is successfully written</span></span>
|
||||
<span id="cb3-24"><a href="conversion-and-downcast.html#cb3-24" aria-hidden="true"></a> <span class="co">// to an m4a file!</span></span>
|
||||
<span id="cb3-25"><a href="conversion-and-downcast.html#cb3-25" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(mp4tag<span class="op">.</span>title()<span class="op">,</span> <span class="cn">Some</span>(<span class="st">"title from mp3 file"</span>))<span class="op">;</span></span>
|
||||
<span id="cb3-26"><a href="conversion-and-downcast.html#cb3-26" aria-hidden="true"></a> <span class="co">// multiple artists</span></span>
|
||||
<span id="cb3-27"><a href="conversion-and-downcast.html#cb3-27" aria-hidden="true"></a> mp4tag<span class="op">.</span>add_artist(<span class="st">"artist1 of mp4"</span>)<span class="op">;</span></span>
|
||||
<span id="cb3-28"><a href="conversion-and-downcast.html#cb3-28" aria-hidden="true"></a> mp4tag<span class="op">.</span>add_artist(<span class="st">"artist2 of mp4"</span>)<span class="op">;</span></span>
|
||||
<span id="cb3-29"><a href="conversion-and-downcast.html#cb3-29" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(</span>
|
||||
<span id="cb3-30"><a href="conversion-and-downcast.html#cb3-30" aria-hidden="true"></a> mp4tag<span class="op">.</span>artists()<span class="op">,</span></span>
|
||||
<span id="cb3-31"><a href="conversion-and-downcast.html#cb3-31" aria-hidden="true"></a> <span class="cn">Some</span>(<span class="pp">vec!</span>[<span class="st">"artist1 of mp4"</span><span class="op">,</span> <span class="st">"artist2 of mp4"</span>])</span>
|
||||
<span id="cb3-32"><a href="conversion-and-downcast.html#cb3-32" aria-hidden="true"></a> )<span class="op">;</span></span>
|
||||
<span id="cb3-33"><a href="conversion-and-downcast.html#cb3-33" aria-hidden="true"></a> <span class="co">// convert to id3 tag, which does not support multiple artists</span></span>
|
||||
<span id="cb3-34"><a href="conversion-and-downcast.html#cb3-34" aria-hidden="true"></a> mp4tag<span class="op">.</span>set_config(<span class="pp">Config::</span><span class="kw">default</span>()<span class="op">.</span>sep_artist(<span class="st">"/"</span>))<span class="op">;</span></span>
|
||||
<span id="cb3-35"><a href="conversion-and-downcast.html#cb3-35" aria-hidden="true"></a> <span class="co">// separator is by default `;` but we can customise it</span></span>
|
||||
<span id="cb3-36"><a href="conversion-and-downcast.html#cb3-36" aria-hidden="true"></a> <span class="kw">let</span> mp3tag <span class="op">=</span> mp4tag<span class="op">.</span>to_dyn_tag(<span class="pp">TagType::</span>Id3v2)<span class="op">;</span></span>
|
||||
<span id="cb3-37"><a href="conversion-and-downcast.html#cb3-37" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(mp3tag<span class="op">.</span>artist()<span class="op">,</span> <span class="cn">Some</span>(<span class="st">"artist1 of mp4/artist2 of mp4"</span>))<span class="op">;</span></span>
|
||||
<span id="cb3-38"><a href="conversion-and-downcast.html#cb3-38" aria-hidden="true"></a><span class="op">}</span></span></code></pre></div>
|
||||
</div>
|
||||
<div id="converting-into-a-concrete-type-downcasting" class="section level2" number="2.2">
|
||||
<h2><span class="header-section-number">2.2</span> Converting into a Concrete Type (Downcasting)</h2>
|
||||
<blockquote>
|
||||
<p>Can I convert into a concrete type?</p>
|
||||
</blockquote>
|
||||
<p>Yes, you can directly convert <code>.into()</code> it (this is technically known as a “downcast”):</p>
|
||||
<div class="sourceCode" id="cb4"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb4-1"><a href="conversion-and-downcast.html#cb4-1" aria-hidden="true"></a><span class="kw">use</span> <span class="pp">audiotags::</span><span class="op">{</span>FlacTag<span class="op">,</span> Tag<span class="op">};</span></span>
|
||||
<span id="cb4-2"><a href="conversion-and-downcast.html#cb4-2" aria-hidden="true"></a></span>
|
||||
<span id="cb4-3"><a href="conversion-and-downcast.html#cb4-3" aria-hidden="true"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
|
||||
<span id="cb4-4"><a href="conversion-and-downcast.html#cb4-4" aria-hidden="true"></a> <span class="kw">let</span> id3v2tag <span class="op">=</span> <span class="pp">Tag::</span><span class="kw">default</span>()<span class="op">.</span>read_from_path(<span class="st">"assets/a.mp3"</span>)<span class="op">.</span>unwrap()<span class="op">;</span></span>
|
||||
<span id="cb4-5"><a href="conversion-and-downcast.html#cb4-5" aria-hidden="true"></a> <span class="kw">let</span> _flactag<span class="op">:</span> FlacTag <span class="op">=</span> id3v2tag<span class="op">.</span>into()<span class="op">;</span></span>
|
||||
<span id="cb4-6"><a href="conversion-and-downcast.html#cb4-6" aria-hidden="true"></a> <span class="co">// of course, you can `let id3v2tag_concrete: Id3v2Tag = id3v2tag.into();`</span></span>
|
||||
<span id="cb4-7"><a href="conversion-and-downcast.html#cb4-7" aria-hidden="true"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>You can even convert <code>.into()</code> the ‘backend’ tag type:</p>
|
||||
<div class="sourceCode" id="cb5"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb5-1"><a href="conversion-and-downcast.html#cb5-1" aria-hidden="true"></a><span class="kw">use</span> <span class="pp">audiotags::</span>Tag<span class="op">;</span></span>
|
||||
<span id="cb5-2"><a href="conversion-and-downcast.html#cb5-2" aria-hidden="true"></a></span>
|
||||
<span id="cb5-3"><a href="conversion-and-downcast.html#cb5-3" aria-hidden="true"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
|
||||
<span id="cb5-4"><a href="conversion-and-downcast.html#cb5-4" aria-hidden="true"></a> <span class="kw">let</span> mp3tag <span class="op">=</span> <span class="pp">Tag::</span><span class="kw">default</span>()<span class="op">.</span>read_from_path(<span class="st">"assets/a.mp3"</span>)<span class="op">.</span>unwrap()<span class="op">;</span></span>
|
||||
<span id="cb5-5"><a href="conversion-and-downcast.html#cb5-5" aria-hidden="true"></a> <span class="kw">let</span> flactag<span class="op">:</span> <span class="pp">metaflac::</span>Tag <span class="op">=</span> mp3tag<span class="op">.</span>into()<span class="op">;</span> <span class="co">// into the 'backend' tag</span></span>
|
||||
<span id="cb5-6"><a href="conversion-and-downcast.html#cb5-6" aria-hidden="true"></a> <span class="co">// then you can use methods specific to metaflac</span></span>
|
||||
<span id="cb5-7"><a href="conversion-and-downcast.html#cb5-7" aria-hidden="true"></a> <span class="kw">let</span> _ <span class="op">=</span> flactag<span class="op">.</span>get_streaminfo()<span class="op">;</span></span>
|
||||
<span id="cb5-8"><a href="conversion-and-downcast.html#cb5-8" aria-hidden="true"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>This is useful when you really need to use the methods not provided by <code>audiotags::traits::*</code>.</p>
|
||||
<p>You can also downcast the concrete <code>audiotags::FlacTag</code> to <code>metaflac::Tag</code> and so no.</p>
|
||||
</div>
|
||||
<div id="upcasting" class="section level2" number="2.3">
|
||||
<h2><span class="header-section-number">2.3</span> Upcasting</h2>
|
||||
<p>Since you’re allowed to downcast, naturally you can also upcast:</p>
|
||||
<div class="sourceCode" id="cb6"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb6-1"><a href="conversion-and-downcast.html#cb6-1" aria-hidden="true"></a><span class="kw">use</span> <span class="pp">audiotags::</span><span class="op">*;</span></span>
|
||||
<span id="cb6-2"><a href="conversion-and-downcast.html#cb6-2" aria-hidden="true"></a></span>
|
||||
<span id="cb6-3"><a href="conversion-and-downcast.html#cb6-3" aria-hidden="true"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
|
||||
<span id="cb6-4"><a href="conversion-and-downcast.html#cb6-4" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> innertag <span class="op">=</span> <span class="pp">metaflac::Tag::</span><span class="kw">default</span>()<span class="op">;</span></span>
|
||||
<span id="cb6-5"><a href="conversion-and-downcast.html#cb6-5" aria-hidden="true"></a> innertag</span>
|
||||
<span id="cb6-6"><a href="conversion-and-downcast.html#cb6-6" aria-hidden="true"></a> <span class="op">.</span>vorbis_comments_mut()</span>
|
||||
<span id="cb6-7"><a href="conversion-and-downcast.html#cb6-7" aria-hidden="true"></a> <span class="op">.</span>set_title(<span class="pp">vec!</span>[<span class="st">"title from metaflac::Tag"</span>])<span class="op">;</span></span>
|
||||
<span id="cb6-8"><a href="conversion-and-downcast.html#cb6-8" aria-hidden="true"></a> <span class="kw">let</span> tag<span class="op">:</span> FlacTag <span class="op">=</span> innertag<span class="op">.</span>into()<span class="op">;</span></span>
|
||||
<span id="cb6-9"><a href="conversion-and-downcast.html#cb6-9" aria-hidden="true"></a> <span class="kw">let</span> _id3tag <span class="op">=</span> tag<span class="op">.</span>to_dyn_tag(<span class="pp">TagType::</span>Id3v2)<span class="op">;</span></span>
|
||||
<span id="cb6-10"><a href="conversion-and-downcast.html#cb6-10" aria-hidden="true"></a> <span class="co">// in this case the "title" metadata will be</span></span>
|
||||
<span id="cb6-11"><a href="conversion-and-downcast.html#cb6-11" aria-hidden="true"></a> <span class="co">// losslessly written into the id3tag.</span></span>
|
||||
<span id="cb6-12"><a href="conversion-and-downcast.html#cb6-12" aria-hidden="true"></a> <span class="co">// However, if you have FLAC-specific fields,</span></span>
|
||||
<span id="cb6-13"><a href="conversion-and-downcast.html#cb6-13" aria-hidden="true"></a> <span class="co">// they will be lost upon conversion</span></span>
|
||||
<span id="cb6-14"><a href="conversion-and-downcast.html#cb6-14" aria-hidden="true"></a><span class="op">}</span></span></code></pre></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="start-simple.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
|
||||
<a href="anytag.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<script src="libs/gitbook-2.6.7/js/app.min.js"></script>
|
||||
<script src="libs/gitbook-2.6.7/js/lunr.js"></script>
|
||||
<script src="libs/gitbook-2.6.7/js/clipboard.min.js"></script>
|
||||
<script src="libs/gitbook-2.6.7/js/plugin-search.js"></script>
|
||||
<script src="libs/gitbook-2.6.7/js/plugin-sharing.js"></script>
|
||||
<script src="libs/gitbook-2.6.7/js/plugin-fontsettings.js"></script>
|
||||
<script src="libs/gitbook-2.6.7/js/plugin-bookdown.js"></script>
|
||||
<script src="libs/gitbook-2.6.7/js/jquery.highlight.js"></script>
|
||||
<script src="libs/gitbook-2.6.7/js/plugin-clipboard.js"></script>
|
||||
<script>
|
||||
gitbook.require(["gitbook"], function(gitbook) {
|
||||
gitbook.start({
|
||||
"sharing": {
|
||||
"github": false,
|
||||
"facebook": true,
|
||||
"twitter": true,
|
||||
"linkedin": false,
|
||||
"weibo": false,
|
||||
"instapaper": false,
|
||||
"vk": false,
|
||||
"all": ["facebook", "twitter", "linkedin", "weibo", "instapaper"]
|
||||
},
|
||||
"fontsettings": {
|
||||
"theme": "white",
|
||||
"family": "sans",
|
||||
"size": 2
|
||||
},
|
||||
"edit": {
|
||||
"link": null,
|
||||
"text": null
|
||||
},
|
||||
"history": {
|
||||
"link": null,
|
||||
"text": null
|
||||
},
|
||||
"view": {
|
||||
"link": null,
|
||||
"text": null
|
||||
},
|
||||
"download": ["audiotags.pdf", "audiotags.epub"],
|
||||
"toc": {
|
||||
"collapse": "subsection"
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -177,7 +177,7 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
|
|||
<span id="cb2-10"><a href="conversion.html#cb2-10" aria-hidden="true"></a> <span class="co">// set the title</span></span>
|
||||
<span id="cb2-11"><a href="conversion.html#cb2-11" aria-hidden="true"></a> mp3tag<span class="op">.</span>set_title(<span class="st">"title from mp3 file"</span>)<span class="op">;</span></span>
|
||||
<span id="cb2-12"><a href="conversion.html#cb2-12" aria-hidden="true"></a> <span class="co">// we can convert it to an mp4 tag and save it to an m4a file.</span></span>
|
||||
<span id="cb2-13"><a href="conversion.html#cb2-13" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> mp4tag <span class="op">=</span> mp3tag<span class="op">.</span>into_tag(<span class="pp">TagType::</span>Mp4)<span class="op">;</span></span>
|
||||
<span id="cb2-13"><a href="conversion.html#cb2-13" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> mp4tag <span class="op">=</span> mp3tag<span class="op">.</span>to_dyn_tag(<span class="pp">TagType::</span>Mp4)<span class="op">;</span></span>
|
||||
<span id="cb2-14"><a href="conversion.html#cb2-14" aria-hidden="true"></a> mp4tag<span class="op">.</span>write_to_path(M4A_FILE)<span class="op">.</span>unwrap()<span class="op">;</span></span>
|
||||
<span id="cb2-15"><a href="conversion.html#cb2-15" aria-hidden="true"></a></span>
|
||||
<span id="cb2-16"><a href="conversion.html#cb2-16" aria-hidden="true"></a> <span class="co">// reload the tag from the m4a file; this time specifying the</span></span>
|
||||
|
@ -198,7 +198,7 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
|
|||
<span id="cb2-31"><a href="conversion.html#cb2-31" aria-hidden="true"></a> <span class="co">// convert to id3 tag, which does not support multiple artists</span></span>
|
||||
<span id="cb2-32"><a href="conversion.html#cb2-32" aria-hidden="true"></a> mp4tag<span class="op">.</span>set_config(<span class="pp">Config::</span><span class="kw">default</span>()<span class="op">.</span>sep_artist(<span class="st">"/"</span>))<span class="op">;</span></span>
|
||||
<span id="cb2-33"><a href="conversion.html#cb2-33" aria-hidden="true"></a> <span class="co">// separator is by default `;` but we can customise it</span></span>
|
||||
<span id="cb2-34"><a href="conversion.html#cb2-34" aria-hidden="true"></a> <span class="kw">let</span> mp3tag <span class="op">=</span> mp4tag<span class="op">.</span>into_tag(<span class="pp">TagType::</span>Id3v2)<span class="op">;</span></span>
|
||||
<span id="cb2-34"><a href="conversion.html#cb2-34" aria-hidden="true"></a> <span class="kw">let</span> mp3tag <span class="op">=</span> mp4tag<span class="op">.</span>to_dyn_tag(<span class="pp">TagType::</span>Id3v2)<span class="op">;</span></span>
|
||||
<span id="cb2-35"><a href="conversion.html#cb2-35" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(mp3tag<span class="op">.</span>artist()<span class="op">,</span> <span class="cn">Some</span>(<span class="st">"artist1 of mp4/artist2 of mp4"</span>))<span class="op">;</span></span>
|
||||
<span id="cb2-36"><a href="conversion.html#cb2-36" aria-hidden="true"></a><span class="op">}</span></span></code></pre></div>
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
|
|||
<span id="cb4-6"><a href="downcast.html#cb4-6" aria-hidden="true"></a> <span class="op">.</span>vorbis_comments_mut()</span>
|
||||
<span id="cb4-7"><a href="downcast.html#cb4-7" aria-hidden="true"></a> <span class="op">.</span>set_title(<span class="pp">vec!</span>[<span class="st">"title from metaflac::Tag"</span>])<span class="op">;</span></span>
|
||||
<span id="cb4-8"><a href="downcast.html#cb4-8" aria-hidden="true"></a> <span class="kw">let</span> tag<span class="op">:</span> FlacTag <span class="op">=</span> innertag<span class="op">.</span>into()<span class="op">;</span></span>
|
||||
<span id="cb4-9"><a href="downcast.html#cb4-9" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> id3tag <span class="op">=</span> tag<span class="op">.</span>into_tag(<span class="pp">TagType::</span>Id3v2)<span class="op">;</span></span>
|
||||
<span id="cb4-9"><a href="downcast.html#cb4-9" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> id3tag <span class="op">=</span> tag<span class="op">.</span>to_dyn_tag(<span class="pp">TagType::</span>Id3v2)<span class="op">;</span></span>
|
||||
<span id="cb4-10"><a href="downcast.html#cb4-10" aria-hidden="true"></a> id3tag</span>
|
||||
<span id="cb4-11"><a href="downcast.html#cb4-11" aria-hidden="true"></a> <span class="op">.</span>write_to_path(<span class="st">"assets/a.mp3"</span>)</span>
|
||||
<span id="cb4-12"><a href="downcast.html#cb4-12" aria-hidden="true"></a> <span class="op">.</span>expect(<span class="st">"Fail to write!"</span>)<span class="op">;</span></span>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<meta name="author" content="Tianyi Shi" />
|
||||
|
||||
|
||||
<meta name="date" content="2020-10-27" />
|
||||
<meta name="date" content="2020-10-29" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
|
@ -138,10 +138,13 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
|
|||
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#examples-in-this-manual"><i class="fa fa-check"></i>Examples in this manual</a></li>
|
||||
</ul></li>
|
||||
<li class="chapter" data-level="1" data-path="start-simple.html"><a href="start-simple.html"><i class="fa fa-check"></i><b>1</b> Start Simple</a></li>
|
||||
<li class="chapter" data-level="2" data-path="conversion.html"><a href="conversion.html"><i class="fa fa-check"></i><b>2</b> Conversion</a></li>
|
||||
<li class="chapter" data-level="2" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html"><i class="fa fa-check"></i><b>2</b> Conversion and Downcast</a>
|
||||
<ul>
|
||||
<li class="chapter" data-level="2.1" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html#converting-from-a-boxdyn-audiotag-to-another"><i class="fa fa-check"></i><b>2.1</b> Converting from a <code>Box<dyn AudioTag</code> to Another</a></li>
|
||||
<li class="chapter" data-level="2.2" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html#converting-into-a-concrete-type-downcasting"><i class="fa fa-check"></i><b>2.2</b> Converting into a Concrete Type (Downcasting)</a></li>
|
||||
<li class="chapter" data-level="2.3" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html#upcasting"><i class="fa fa-check"></i><b>2.3</b> Upcasting</a></li>
|
||||
</ul></li>
|
||||
<li class="chapter" data-level="3" data-path="anytag.html"><a href="anytag.html"><i class="fa fa-check"></i><b>3</b> <code>AnyTag</code></a></li>
|
||||
<li class="chapter" data-level="4" data-path="downcast.html"><a href="downcast.html"><i class="fa fa-check"></i><b>4</b> Downcast</a></li>
|
||||
<li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>References</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li>
|
||||
|
||||
|
@ -165,7 +168,7 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
|
|||
<div id="header">
|
||||
<h1 class="title">audiotags Manual</h1>
|
||||
<p class="author"><em>Tianyi Shi</em></p>
|
||||
<p class="date"><em>2020-10-27</em></p>
|
||||
<p class="date"><em>2020-10-29</em></p>
|
||||
</div>
|
||||
<div id="preface" class="section level1 unnumbered">
|
||||
<h1>Preface</h1>
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
start-simple
|
||||
conversion
|
||||
conversion-and-downcast
|
||||
converting-from-a-boxdyn-audiotag-to-another
|
||||
converting-into-a-concrete-type-downcasting
|
||||
upcasting
|
||||
anytag
|
||||
downcast
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -4,11 +4,11 @@
|
|||
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Chapter 1 Start Simple | audiotags Manual</title>
|
||||
<title>1 Start Simple | audiotags Manual</title>
|
||||
<meta name="description" content="This is the manual of the Rust crate ‘audiotags’" />
|
||||
<meta name="generator" content="bookdown 0.21 and GitBook 2.6.7" />
|
||||
|
||||
<meta property="og:title" content="Chapter 1 Start Simple | audiotags Manual" />
|
||||
<meta property="og:title" content="1 Start Simple | audiotags Manual" />
|
||||
<meta property="og:type" content="book" />
|
||||
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
|||
|
||||
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:title" content="Chapter 1 Start Simple | audiotags Manual" />
|
||||
<meta name="twitter:title" content="1 Start Simple | audiotags Manual" />
|
||||
|
||||
<meta name="twitter:description" content="This is the manual of the Rust crate ‘audiotags’" />
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
|||
<meta name="author" content="Tianyi Shi" />
|
||||
|
||||
|
||||
<meta name="date" content="2020-10-27" />
|
||||
<meta name="date" content="2020-10-29" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
|
@ -32,7 +32,7 @@
|
|||
|
||||
|
||||
<link rel="prev" href="index.html"/>
|
||||
<link rel="next" href="conversion.html"/>
|
||||
<link rel="next" href="conversion-and-downcast.html"/>
|
||||
<script src="libs/header-attrs-2.4/header-attrs.js"></script>
|
||||
<script src="libs/jquery-2.2.3/jquery.min.js"></script>
|
||||
<link href="libs/gitbook-2.6.7/css/style.css" rel="stylesheet" />
|
||||
|
@ -138,10 +138,13 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
|
|||
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#examples-in-this-manual"><i class="fa fa-check"></i>Examples in this manual</a></li>
|
||||
</ul></li>
|
||||
<li class="chapter" data-level="1" data-path="start-simple.html"><a href="start-simple.html"><i class="fa fa-check"></i><b>1</b> Start Simple</a></li>
|
||||
<li class="chapter" data-level="2" data-path="conversion.html"><a href="conversion.html"><i class="fa fa-check"></i><b>2</b> Conversion</a></li>
|
||||
<li class="chapter" data-level="2" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html"><i class="fa fa-check"></i><b>2</b> Conversion and Downcast</a>
|
||||
<ul>
|
||||
<li class="chapter" data-level="2.1" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html#converting-from-a-boxdyn-audiotag-to-another"><i class="fa fa-check"></i><b>2.1</b> Converting from a <code>Box<dyn AudioTag</code> to Another</a></li>
|
||||
<li class="chapter" data-level="2.2" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html#converting-into-a-concrete-type-downcasting"><i class="fa fa-check"></i><b>2.2</b> Converting into a Concrete Type (Downcasting)</a></li>
|
||||
<li class="chapter" data-level="2.3" data-path="conversion-and-downcast.html"><a href="conversion-and-downcast.html#upcasting"><i class="fa fa-check"></i><b>2.3</b> Upcasting</a></li>
|
||||
</ul></li>
|
||||
<li class="chapter" data-level="3" data-path="anytag.html"><a href="anytag.html"><i class="fa fa-check"></i><b>3</b> <code>AnyTag</code></a></li>
|
||||
<li class="chapter" data-level="4" data-path="downcast.html"><a href="downcast.html"><i class="fa fa-check"></i><b>4</b> Downcast</a></li>
|
||||
<li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>References</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="https://github.com/rstudio/bookdown" target="blank">Published with bookdown</a></li>
|
||||
|
||||
|
@ -163,42 +166,55 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
|
|||
|
||||
<section class="normal" id="section-">
|
||||
<div id="start-simple" class="section level1" number="1">
|
||||
<h1><span class="header-section-number">Chapter 1</span> Start Simple</h1>
|
||||
<h1><span class="header-section-number">1</span> Start Simple</h1>
|
||||
<p>The following example shows how you can read an audio file, parse, set, and save its metadata:</p>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb1-1"><a href="start-simple.html#cb1-1" aria-hidden="true"></a><span class="kw">use</span> <span class="pp">audiotags::</span><span class="op">{</span>MimeType<span class="op">,</span> Picture<span class="op">,</span> Tag<span class="op">,</span> TagType<span class="op">};</span></span>
|
||||
<span id="cb1-2"><a href="start-simple.html#cb1-2" aria-hidden="true"></a></span>
|
||||
<span id="cb1-3"><a href="start-simple.html#cb1-3" aria-hidden="true"></a><span class="kw">const</span> MP3_FILE<span class="op">:</span> <span class="op">&</span><span class="ot">'static</span> <span class="dt">str</span> <span class="op">=</span> <span class="st">"assets/a.mp3"</span><span class="op">;</span></span>
|
||||
<span id="cb1-4"><a href="start-simple.html#cb1-4" aria-hidden="true"></a></span>
|
||||
<span id="cb1-5"><a href="start-simple.html#cb1-5" aria-hidden="true"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
|
||||
<span id="cb1-6"><a href="start-simple.html#cb1-6" aria-hidden="true"></a> <span class="co">// using `default()` so that the metadata format is guessed</span></span>
|
||||
<span id="cb1-7"><a href="start-simple.html#cb1-7" aria-hidden="true"></a> <span class="co">// (from the file extension) (in this case, Id3v2 tag is read)</span></span>
|
||||
<span id="cb1-8"><a href="start-simple.html#cb1-8" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> tag <span class="op">=</span> <span class="pp">Tag::</span><span class="kw">default</span>()<span class="op">.</span>read_from_path(MP3_FILE)<span class="op">.</span>unwrap()<span class="op">;</span></span>
|
||||
<span id="cb1-9"><a href="start-simple.html#cb1-9" aria-hidden="true"></a> <span class="co">// You can also specify the metadata format (tag type):</span></span>
|
||||
<span id="cb1-10"><a href="start-simple.html#cb1-10" aria-hidden="true"></a> <span class="kw">let</span> _tag <span class="op">=</span> <span class="pp">Tag::</span>with_tag_type(<span class="pp">TagType::</span>Id3v2)</span>
|
||||
<span id="cb1-11"><a href="start-simple.html#cb1-11" aria-hidden="true"></a> <span class="op">.</span>read_from_path(MP3_FILE)</span>
|
||||
<span id="cb1-12"><a href="start-simple.html#cb1-12" aria-hidden="true"></a> <span class="op">.</span>expect(<span class="st">"Fail to read!"</span>)<span class="op">;</span></span>
|
||||
<span id="cb1-13"><a href="start-simple.html#cb1-13" aria-hidden="true"></a></span>
|
||||
<span id="cb1-14"><a href="start-simple.html#cb1-14" aria-hidden="true"></a> tag<span class="op">.</span>set_title(<span class="st">"foo title"</span>)<span class="op">;</span></span>
|
||||
<span id="cb1-15"><a href="start-simple.html#cb1-15" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(tag<span class="op">.</span>title()<span class="op">,</span> <span class="cn">Some</span>(<span class="st">"foo title"</span>))<span class="op">;</span></span>
|
||||
<span id="cb1-16"><a href="start-simple.html#cb1-16" aria-hidden="true"></a> tag<span class="op">.</span>remove_title()<span class="op">;</span></span>
|
||||
<span id="cb1-17"><a href="start-simple.html#cb1-17" aria-hidden="true"></a> <span class="pp">assert!</span>(tag<span class="op">.</span>title()<span class="op">.</span>is_none())<span class="op">;</span></span>
|
||||
<span id="cb1-18"><a href="start-simple.html#cb1-18" aria-hidden="true"></a> tag<span class="op">.</span>remove_title()<span class="op">;</span></span>
|
||||
<span id="cb1-19"><a href="start-simple.html#cb1-19" aria-hidden="true"></a> <span class="co">// trying to remove a field that's already empty won't hurt</span></span>
|
||||
<span id="cb1-20"><a href="start-simple.html#cb1-20" aria-hidden="true"></a></span>
|
||||
<span id="cb1-21"><a href="start-simple.html#cb1-21" aria-hidden="true"></a> <span class="kw">let</span> cover <span class="op">=</span> Picture <span class="op">{</span></span>
|
||||
<span id="cb1-22"><a href="start-simple.html#cb1-22" aria-hidden="true"></a> mime_type<span class="op">:</span> <span class="pp">MimeType::</span>Jpeg<span class="op">,</span></span>
|
||||
<span id="cb1-23"><a href="start-simple.html#cb1-23" aria-hidden="true"></a> data<span class="op">:</span> <span class="op">&</span><span class="pp">vec!</span>[<span class="dv">0u8</span><span class="op">;</span> <span class="dv">10</span>]<span class="op">,</span></span>
|
||||
<span id="cb1-24"><a href="start-simple.html#cb1-24" aria-hidden="true"></a> <span class="op">};</span></span>
|
||||
<span id="cb1-25"><a href="start-simple.html#cb1-25" aria-hidden="true"></a></span>
|
||||
<span id="cb1-26"><a href="start-simple.html#cb1-26" aria-hidden="true"></a> tag<span class="op">.</span>set_album_cover(cover<span class="op">.</span>clone())<span class="op">;</span></span>
|
||||
<span id="cb1-27"><a href="start-simple.html#cb1-27" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(tag<span class="op">.</span>album_cover()<span class="op">,</span> <span class="cn">Some</span>(cover))<span class="op">;</span></span>
|
||||
<span id="cb1-28"><a href="start-simple.html#cb1-28" aria-hidden="true"></a> tag<span class="op">.</span>remove_album_cover()<span class="op">;</span></span>
|
||||
<span id="cb1-29"><a href="start-simple.html#cb1-29" aria-hidden="true"></a> <span class="pp">assert!</span>(tag<span class="op">.</span>album_cover()<span class="op">.</span>is_none())<span class="op">;</span></span>
|
||||
<span id="cb1-30"><a href="start-simple.html#cb1-30" aria-hidden="true"></a> tag<span class="op">.</span>remove_album_cover()<span class="op">;</span></span>
|
||||
<span id="cb1-31"><a href="start-simple.html#cb1-31" aria-hidden="true"></a></span>
|
||||
<span id="cb1-32"><a href="start-simple.html#cb1-32" aria-hidden="true"></a> tag<span class="op">.</span>save_to_path(MP3_FILE)<span class="op">.</span>expect(<span class="st">"Fail to save"</span>)<span class="op">;</span></span>
|
||||
<span id="cb1-33"><a href="start-simple.html#cb1-33" aria-hidden="true"></a> <span class="co">// </span><span class="al">TASK</span><span class="co">: reload the file and prove the data have been saved</span></span>
|
||||
<span id="cb1-34"><a href="start-simple.html#cb1-34" aria-hidden="true"></a><span class="op">}</span></span></code></pre></div>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb1-1"><a href="start-simple.html#cb1-1" aria-hidden="true"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
|
||||
<span id="cb1-2"><a href="start-simple.html#cb1-2" aria-hidden="true"></a> <span class="co">// using `default()` or `new()` alone so that the metadata format is</span></span>
|
||||
<span id="cb1-3"><a href="start-simple.html#cb1-3" aria-hidden="true"></a> <span class="co">// guessed (from the file extension) (in this case, Id3v2 tag is read)</span></span>
|
||||
<span id="cb1-4"><a href="start-simple.html#cb1-4" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> tag <span class="op">=</span> <span class="pp">Tag::</span>new()<span class="op">.</span>read_from_path(MP3_FILE)<span class="op">.</span>unwrap()<span class="op">;</span></span>
|
||||
<span id="cb1-5"><a href="start-simple.html#cb1-5" aria-hidden="true"></a> <span class="co">// You can also specify the metadata format (tag type):</span></span>
|
||||
<span id="cb1-6"><a href="start-simple.html#cb1-6" aria-hidden="true"></a> <span class="kw">let</span> _tag <span class="op">=</span> <span class="pp">Tag::</span>new()</span>
|
||||
<span id="cb1-7"><a href="start-simple.html#cb1-7" aria-hidden="true"></a> <span class="op">.</span>with_tag_type(<span class="pp">TagType::</span>Id3v2)</span>
|
||||
<span id="cb1-8"><a href="start-simple.html#cb1-8" aria-hidden="true"></a> <span class="op">.</span>read_from_path(MP3_FILE)</span>
|
||||
<span id="cb1-9"><a href="start-simple.html#cb1-9" aria-hidden="true"></a> <span class="op">.</span>expect(<span class="st">"Fail to read!"</span>)<span class="op">;</span></span>
|
||||
<span id="cb1-10"><a href="start-simple.html#cb1-10" aria-hidden="true"></a></span>
|
||||
<span id="cb1-11"><a href="start-simple.html#cb1-11" aria-hidden="true"></a> tag<span class="op">.</span>set_title(<span class="st">"foo title"</span>)<span class="op">;</span></span>
|
||||
<span id="cb1-12"><a href="start-simple.html#cb1-12" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(tag<span class="op">.</span>title()<span class="op">,</span> <span class="cn">Some</span>(<span class="st">"foo title"</span>))<span class="op">;</span></span>
|
||||
<span id="cb1-13"><a href="start-simple.html#cb1-13" aria-hidden="true"></a> tag<span class="op">.</span>remove_title()<span class="op">;</span></span>
|
||||
<span id="cb1-14"><a href="start-simple.html#cb1-14" aria-hidden="true"></a> <span class="pp">assert!</span>(tag<span class="op">.</span>title()<span class="op">.</span>is_none())<span class="op">;</span></span>
|
||||
<span id="cb1-15"><a href="start-simple.html#cb1-15" aria-hidden="true"></a> tag<span class="op">.</span>remove_title()<span class="op">;</span></span>
|
||||
<span id="cb1-16"><a href="start-simple.html#cb1-16" aria-hidden="true"></a> <span class="co">// trying to remove a field that's already empty won't hurt</span></span>
|
||||
<span id="cb1-17"><a href="start-simple.html#cb1-17" aria-hidden="true"></a></span>
|
||||
<span id="cb1-18"><a href="start-simple.html#cb1-18" aria-hidden="true"></a> <span class="kw">let</span> cover <span class="op">=</span> Picture <span class="op">{</span></span>
|
||||
<span id="cb1-19"><a href="start-simple.html#cb1-19" aria-hidden="true"></a> mime_type<span class="op">:</span> <span class="pp">MimeType::</span>Jpeg<span class="op">,</span></span>
|
||||
<span id="cb1-20"><a href="start-simple.html#cb1-20" aria-hidden="true"></a> data<span class="op">:</span> <span class="op">&</span><span class="pp">vec!</span>[<span class="dv">0u8</span><span class="op">;</span> <span class="dv">10</span>]<span class="op">,</span></span>
|
||||
<span id="cb1-21"><a href="start-simple.html#cb1-21" aria-hidden="true"></a> <span class="op">};</span></span>
|
||||
<span id="cb1-22"><a href="start-simple.html#cb1-22" aria-hidden="true"></a></span>
|
||||
<span id="cb1-23"><a href="start-simple.html#cb1-23" aria-hidden="true"></a> tag<span class="op">.</span>set_album_cover(cover<span class="op">.</span>clone())<span class="op">;</span></span>
|
||||
<span id="cb1-24"><a href="start-simple.html#cb1-24" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(tag<span class="op">.</span>album_cover()<span class="op">,</span> <span class="cn">Some</span>(cover))<span class="op">;</span></span>
|
||||
<span id="cb1-25"><a href="start-simple.html#cb1-25" aria-hidden="true"></a> tag<span class="op">.</span>remove_album_cover()<span class="op">;</span></span>
|
||||
<span id="cb1-26"><a href="start-simple.html#cb1-26" aria-hidden="true"></a> <span class="pp">assert!</span>(tag<span class="op">.</span>album_cover()<span class="op">.</span>is_none())<span class="op">;</span></span>
|
||||
<span id="cb1-27"><a href="start-simple.html#cb1-27" aria-hidden="true"></a> tag<span class="op">.</span>remove_album_cover()<span class="op">;</span></span>
|
||||
<span id="cb1-28"><a href="start-simple.html#cb1-28" aria-hidden="true"></a></span>
|
||||
<span id="cb1-29"><a href="start-simple.html#cb1-29" aria-hidden="true"></a> tag<span class="op">.</span>write_to_path(MP3_FILE)<span class="op">.</span>expect(<span class="st">"Fail to save"</span>)<span class="op">;</span></span>
|
||||
<span id="cb1-30"><a href="start-simple.html#cb1-30" aria-hidden="true"></a> <span class="co">// </span><span class="al">TASK</span><span class="co">: reload the file and prove the data have been saved</span></span>
|
||||
<span id="cb1-31"><a href="start-simple.html#cb1-31" aria-hidden="true"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>Note that <code>Tag</code> always reads into a <code>Box<dyn AudioTag></code>. If you do not want a trait object, you can use the underlying concrete types. However, you’ll also need to manually bring the traits into scope if you prefer not to write <code>audiotags::*</code>.</p>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb2-1"><a href="start-simple.html#cb2-1" aria-hidden="true"></a><span class="kw">use</span> <span class="pp">audiotags::</span><span class="op">{</span><span class="pp">traits::</span><span class="op">*,</span> FlacTag<span class="op">,</span> Id3v2Tag<span class="op">,</span> Mp4Tag<span class="op">};</span></span>
|
||||
<span id="cb2-2"><a href="start-simple.html#cb2-2" aria-hidden="true"></a><span class="co">// or alternatively `use audiotags::*`</span></span>
|
||||
<span id="cb2-3"><a href="start-simple.html#cb2-3" aria-hidden="true"></a></span>
|
||||
<span id="cb2-4"><a href="start-simple.html#cb2-4" aria-hidden="true"></a><span class="kw">fn</span> main() <span class="op">{</span></span>
|
||||
<span id="cb2-5"><a href="start-simple.html#cb2-5" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> tag <span class="op">=</span> <span class="pp">FlacTag::</span>read_from_path(<span class="st">"assets/a.flac"</span>)<span class="op">.</span>unwrap()<span class="op">;</span></span>
|
||||
<span id="cb2-6"><a href="start-simple.html#cb2-6" aria-hidden="true"></a> tag<span class="op">.</span>set_title(<span class="st">"foo"</span>)<span class="op">;</span></span>
|
||||
<span id="cb2-7"><a href="start-simple.html#cb2-7" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(tag<span class="op">.</span>title()<span class="op">,</span> <span class="cn">Some</span>(<span class="st">"foo"</span>))<span class="op">;</span></span>
|
||||
<span id="cb2-8"><a href="start-simple.html#cb2-8" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> tag <span class="op">=</span> <span class="pp">Mp4Tag::</span>read_from_path(<span class="st">"assets/a.m4a"</span>)<span class="op">.</span>unwrap()<span class="op">;</span></span>
|
||||
<span id="cb2-9"><a href="start-simple.html#cb2-9" aria-hidden="true"></a> tag<span class="op">.</span>set_title(<span class="st">"foo"</span>)<span class="op">;</span></span>
|
||||
<span id="cb2-10"><a href="start-simple.html#cb2-10" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(tag<span class="op">.</span>title()<span class="op">,</span> <span class="cn">Some</span>(<span class="st">"foo"</span>))<span class="op">;</span></span>
|
||||
<span id="cb2-11"><a href="start-simple.html#cb2-11" aria-hidden="true"></a> <span class="kw">let</span> <span class="kw">mut</span> tag <span class="op">=</span> <span class="pp">Id3v2Tag::</span>read_from_path(<span class="st">"assets/a.mp3"</span>)<span class="op">.</span>unwrap()<span class="op">;</span></span>
|
||||
<span id="cb2-12"><a href="start-simple.html#cb2-12" aria-hidden="true"></a> tag<span class="op">.</span>set_title(<span class="st">"foo"</span>)<span class="op">;</span></span>
|
||||
<span id="cb2-13"><a href="start-simple.html#cb2-13" aria-hidden="true"></a> <span class="pp">assert_eq!</span>(tag<span class="op">.</span>title()<span class="op">,</span> <span class="cn">Some</span>(<span class="st">"foo"</span>))<span class="op">;</span></span>
|
||||
<span id="cb2-14"><a href="start-simple.html#cb2-14" aria-hidden="true"></a> <span class="co">// all other methods in trait `AudioTagEdit` are available, not just title</span></span>
|
||||
<span id="cb2-15"><a href="start-simple.html#cb2-15" aria-hidden="true"></a><span class="op">}</span></span></code></pre></div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
@ -207,7 +223,7 @@ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warni
|
|||
</div>
|
||||
</div>
|
||||
<a href="index.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
|
||||
<a href="conversion.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
|
||||
<a href="conversion-and-downcast.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<script src="libs/gitbook-2.6.7/js/app.min.js"></script>
|
||||
|
|
|
@ -13,25 +13,6 @@ pre code {
|
|||
white-space: inherit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@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;
|
||||
font-weight: 400;
|
||||
src: local('Lato Regular'), local('Lato-Regular'),
|
||||
url('https://tianyishi2001.github.io/ox/fonts/lato-v11-latin-regular.woff2') format('woff2'),
|
||||
url('https://tianyishi2001.github.io/ox/fonts/lato-v11-latin-regular.woff') format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "nexus-serif";
|
||||
src: url("https://tianyishi2001.github.io/ox/fonts/nexus-serif/NexusSerifWebPro-Regular.woff");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
book_filename: "audiotags"
|
||||
rmd_files: ["index.Rmd", "simple.Rmd", "convert.Rmd", "anytag.Rmd", "downcast.Rmd"]
|
||||
rmd_files: ["index.Rmd", "simple.Rmd", "convert.Rmd", "anytag.Rmd"] #, "downcast.Rmd"]
|
||||
output_dir: "../docs"
|
||||
delete_merged_file: true
|
||||
# language:
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
# Conversion
|
||||
# Conversion and Downcast
|
||||
|
||||
The following example shows how you can read the tag in an `mp3` file, convert it into an `mp4` tag, and write it to an `m4a` file.
|
||||
|
||||
## Converting from a `Box<dyn AudioTag` to Another
|
||||
|
||||
```rust
|
||||
|
||||
use audiotags::{Config, Tag, TagType};
|
||||
|
||||
fn main() {
|
||||
|
@ -15,12 +18,13 @@ fn main() {
|
|||
// set the title
|
||||
mp3tag.set_title("title from mp3 file");
|
||||
// we can convert it to an mp4 tag and save it to an m4a file.
|
||||
let mut mp4tag = mp3tag.into_tag(TagType::Mp4);
|
||||
let mut mp4tag = mp3tag.to_dyn_tag(TagType::Mp4);
|
||||
mp4tag.write_to_path(M4A_FILE).unwrap();
|
||||
|
||||
// reload the tag from the m4a file; this time specifying the
|
||||
// tag type (you can also use `default()`)
|
||||
let mut mp4tag = Tag::with_tag_type(TagType::Mp4)
|
||||
let mut mp4tag = Tag::new()
|
||||
.with_tag_type(TagType::Mp4)
|
||||
.read_from_path(M4A_FILE)
|
||||
.unwrap();
|
||||
// the tag originated from an mp3 file is successfully written
|
||||
|
@ -36,7 +40,61 @@ fn main() {
|
|||
// convert to id3 tag, which does not support multiple artists
|
||||
mp4tag.set_config(Config::default().sep_artist("/"));
|
||||
// separator is by default `;` but we can customise it
|
||||
let mp3tag = mp4tag.into_tag(TagType::Id3v2);
|
||||
let mp3tag = mp4tag.to_dyn_tag(TagType::Id3v2);
|
||||
assert_eq!(mp3tag.artist(), Some("artist1 of mp4/artist2 of mp4"));
|
||||
}
|
||||
```
|
||||
|
||||
## Converting into a Concrete Type (Downcasting)
|
||||
|
||||
> Can I convert into a concrete type?
|
||||
|
||||
Yes, you can directly convert `.into()` it (this is technically known as a "downcast"):
|
||||
|
||||
```rust
|
||||
use audiotags::{FlacTag, Tag};
|
||||
|
||||
fn main() {
|
||||
let id3v2tag = Tag::default().read_from_path("assets/a.mp3").unwrap();
|
||||
let _flactag: FlacTag = id3v2tag.into();
|
||||
// of course, you can `let id3v2tag_concrete: Id3v2Tag = id3v2tag.into();`
|
||||
}
|
||||
```
|
||||
|
||||
You can even convert `.into()` the 'backend' tag type:
|
||||
|
||||
```rust
|
||||
use audiotags::Tag;
|
||||
|
||||
fn main() {
|
||||
let mp3tag = Tag::default().read_from_path("assets/a.mp3").unwrap();
|
||||
let flactag: metaflac::Tag = mp3tag.into(); // into the 'backend' tag
|
||||
// then you can use methods specific to metaflac
|
||||
let _ = flactag.get_streaminfo();
|
||||
}
|
||||
```
|
||||
|
||||
This is useful when you really need to use the methods not provided by `audiotags::traits::*`.
|
||||
|
||||
You can also downcast the concrete `audiotags::FlacTag` to `metaflac::Tag` and so no.
|
||||
|
||||
## Upcasting
|
||||
|
||||
Since you're allowed to downcast, naturally you can also upcast:
|
||||
|
||||
```rust
|
||||
use audiotags::*;
|
||||
|
||||
fn main() {
|
||||
let mut innertag = metaflac::Tag::default();
|
||||
innertag
|
||||
.vorbis_comments_mut()
|
||||
.set_title(vec!["title from metaflac::Tag"]);
|
||||
let tag: FlacTag = innertag.into();
|
||||
let _id3tag = tag.to_dyn_tag(TagType::Id3v2);
|
||||
// in this case the "title" metadata will be
|
||||
// losslessly written into the id3tag.
|
||||
// However, if you have FLAC-specific fields,
|
||||
// they will be lost upon conversion
|
||||
}
|
||||
```
|
|
@ -11,7 +11,7 @@ fn main() {
|
|||
.vorbis_comments_mut()
|
||||
.set_title(vec!["title from metaflac::Tag"]);
|
||||
let tag: FlacTag = innertag.into();
|
||||
let mut id3tag = tag.into_tag(TagType::Id3v2);
|
||||
let mut id3tag = tag.to_dyn_tag(TagType::Id3v2);
|
||||
id3tag
|
||||
.write_to_path("assets/a.mp3")
|
||||
.expect("Fail to write!");
|
||||
|
|
|
@ -3,16 +3,13 @@
|
|||
The following example shows how you can read an audio file, parse, set, and save its metadata:
|
||||
|
||||
```rust
|
||||
use audiotags::{MimeType, Picture, Tag, TagType};
|
||||
|
||||
const MP3_FILE: &'static str = "assets/a.mp3";
|
||||
|
||||
fn main() {
|
||||
// using `default()` so that the metadata format is guessed
|
||||
// (from the file extension) (in this case, Id3v2 tag is read)
|
||||
let mut tag = Tag::default().read_from_path(MP3_FILE).unwrap();
|
||||
// using `default()` or `new()` alone so that the metadata format is
|
||||
// guessed (from the file extension) (in this case, Id3v2 tag is read)
|
||||
let mut tag = Tag::new().read_from_path(MP3_FILE).unwrap();
|
||||
// You can also specify the metadata format (tag type):
|
||||
let _tag = Tag::with_tag_type(TagType::Id3v2)
|
||||
let _tag = Tag::new()
|
||||
.with_tag_type(TagType::Id3v2)
|
||||
.read_from_path(MP3_FILE)
|
||||
.expect("Fail to read!");
|
||||
|
||||
|
@ -34,7 +31,27 @@ fn main() {
|
|||
assert!(tag.album_cover().is_none());
|
||||
tag.remove_album_cover();
|
||||
|
||||
tag.save_to_path(MP3_FILE).expect("Fail to save");
|
||||
tag.write_to_path(MP3_FILE).expect("Fail to save");
|
||||
// TASK: reload the file and prove the data have been saved
|
||||
}
|
||||
```
|
||||
|
||||
Note that `Tag` always reads into a `Box<dyn AudioTag>`. If you do not want a trait object, you can use the underlying concrete types. However, you'll also need to manually bring the traits into scope if you prefer not to write `audiotags::*`.
|
||||
|
||||
```rust
|
||||
use audiotags::{traits::*, FlacTag, Id3v2Tag, Mp4Tag};
|
||||
// or alternatively `use audiotags::*`
|
||||
|
||||
fn main() {
|
||||
let mut tag = FlacTag::read_from_path("assets/a.flac").unwrap();
|
||||
tag.set_title("foo");
|
||||
assert_eq!(tag.title(), Some("foo"));
|
||||
let mut tag = Mp4Tag::read_from_path("assets/a.m4a").unwrap();
|
||||
tag.set_title("foo");
|
||||
assert_eq!(tag.title(), Some("foo"));
|
||||
let mut tag = Id3v2Tag::read_from_path("assets/a.mp3").unwrap();
|
||||
tag.set_title("foo");
|
||||
assert_eq!(tag.title(), Some("foo"));
|
||||
// all other methods in trait `AudioTagEdit` are available, not just title
|
||||
}
|
||||
```
|
|
@ -13,16 +13,6 @@ pre code {
|
|||
white-space: inherit;
|
||||
}
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Lato Regular'), local('Lato-Regular'),
|
||||
url('https://tianyishi2001.github.io/ox/fonts/lato-v11-latin-regular.woff2') format('woff2'),
|
||||
url('https://tianyishi2001.github.io/ox/fonts/lato-v11-latin-regular.woff') format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "nexus-serif";
|
||||
src: url("https://tianyishi2001.github.io/ox/fonts/nexus-serif/NexusSerifWebPro-Regular.woff");
|
||||
|
|
|
@ -4,10 +4,10 @@ use crate::*;
|
|||
pub struct AnyTag<'a> {
|
||||
pub config: Config,
|
||||
pub title: Option<&'a str>,
|
||||
pub artists: Option<Vec<&'a str>>, // ? iterator
|
||||
pub artists: Option<Vec<&'a str>>,
|
||||
pub year: Option<i32>,
|
||||
pub album_title: Option<&'a str>,
|
||||
pub album_artists: Option<Vec<&'a str>>, // ? iterator
|
||||
pub album_artists: Option<Vec<&'a str>>,
|
||||
pub album_cover: Option<Picture<'a>>,
|
||||
pub track_number: Option<u16>,
|
||||
pub total_tracks: Option<u16>,
|
||||
|
@ -15,10 +15,6 @@ pub struct AnyTag<'a> {
|
|||
pub total_discs: Option<u16>,
|
||||
}
|
||||
|
||||
// impl<'a> From<&'a AnyTag> for AnyTag<'a> {
|
||||
// fn from(inp: &'a AnyTag)
|
||||
// }
|
||||
|
||||
impl AudioTagConfig for AnyTag<'_> {
|
||||
fn config(&self) -> &Config {
|
||||
&self.config
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
/// Error types that could occur in this library.
|
||||
/// Error that could occur in this library.
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("")]
|
||||
DowncastError,
|
||||
|
||||
/// Fail to guess the metadata format based on the file extension.
|
||||
#[error("Fail to guess the metadata format based on the file extension.")]
|
||||
UnknownFileExtension(String),
|
||||
|
|
134
src/lib.rs
134
src/lib.rs
|
@ -55,10 +55,81 @@ use std::path::Path;
|
|||
|
||||
pub use std::convert::{TryFrom, TryInto};
|
||||
|
||||
/// A builder for `Box<dyn AudioTag>`. If you do not want a trait object, you can use individual types.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use audiotags::{Tag, TagType};
|
||||
/// // Guess the format by default
|
||||
/// let mut tag = Tag::new().read_from_path("assets/a.mp3").unwrap();
|
||||
/// tag.set_title("Foo");
|
||||
/// // you can convert the tag type and save the metadata to another file.
|
||||
/// tag.to_dyn_tag(TagType::Mp4).write_to_path("assets/a.m4a");
|
||||
/// // you can specify the tag type (but when you want to do this, also consider directly using the concrete type)
|
||||
/// let tag = Tag::new().with_tag_type(TagType::Mp4).read_from_path("assets/a.m4a").unwrap();
|
||||
/// assert_eq!(tag.title(), Some("Foo"));
|
||||
/// ```
|
||||
#[derive(Default)]
|
||||
pub struct Tag {
|
||||
/// The tag type which can be specified with `.with_tag_type()` before parsing.
|
||||
tag_type: Option<TagType>,
|
||||
/// The config which can be specified with `.with_config()` before parsing.
|
||||
config: Config,
|
||||
}
|
||||
|
||||
impl Tag {
|
||||
/// Initiate a new Tag (a builder for `Box<dyn AudioTag>`) with default configurations.
|
||||
/// You can then optionally chain `with_tag_type` and/or `with_config`.
|
||||
/// Finally, you `read_from_path`
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
/// Specify the tag type
|
||||
pub fn with_tag_type(self, tag_type: TagType) -> Self {
|
||||
Self {
|
||||
tag_type: Some(tag_type),
|
||||
config: self.config,
|
||||
}
|
||||
}
|
||||
/// Specify configuration, if you do not want to use the default
|
||||
pub fn with_config(self, config: Config) -> Self {
|
||||
Self {
|
||||
tag_type: self.tag_type,
|
||||
config: config.clone(),
|
||||
}
|
||||
}
|
||||
pub fn read_from_path(&self, path: impl AsRef<Path>) -> crate::Result<Box<dyn AudioTag>> {
|
||||
match self.tag_type.unwrap_or(TagType::try_from_ext(
|
||||
path.as_ref()
|
||||
.extension()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.to_string()
|
||||
.to_lowercase()
|
||||
.as_str(),
|
||||
)?) {
|
||||
TagType::Id3v2 => Ok(Box::new({
|
||||
let mut t = Id3v2Tag::read_from_path(path)?;
|
||||
t.set_config(self.config.clone());
|
||||
t
|
||||
})),
|
||||
TagType::Mp4 => Ok(Box::new({
|
||||
let mut t = Mp4Tag::read_from_path(path)?;
|
||||
t.set_config(self.config.clone());
|
||||
t
|
||||
})),
|
||||
TagType::Flac => Ok(Box::new({
|
||||
let mut t = FlacTag::read_from_path(path)?;
|
||||
t.set_config(self.config.clone());
|
||||
t
|
||||
})),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum TagType {
|
||||
// /// Guess the tag type based on the file extension
|
||||
// Guess,
|
||||
/// ## Common file extensions
|
||||
///
|
||||
/// `.mp3`
|
||||
|
@ -90,57 +161,10 @@ impl TagType {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Tag {
|
||||
tag_type: Option<TagType>,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
impl Tag {
|
||||
pub fn with_tag_type(tag_type: TagType) -> Self {
|
||||
Self {
|
||||
tag_type: Some(tag_type),
|
||||
config: Config::default(),
|
||||
}
|
||||
}
|
||||
pub fn with_config(config: Config) -> Self {
|
||||
Self {
|
||||
tag_type: None,
|
||||
config: config.clone(),
|
||||
}
|
||||
}
|
||||
pub fn with_tag_type_and_config(tag_type: TagType, config: Config) -> Self {
|
||||
Self {
|
||||
tag_type: Some(tag_type),
|
||||
config: config.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_from_path(&self, path: impl AsRef<Path>) -> crate::Result<Box<dyn AudioTag>> {
|
||||
match self.tag_type.unwrap_or(TagType::try_from_ext(
|
||||
path.as_ref()
|
||||
.extension()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.to_string()
|
||||
.to_lowercase()
|
||||
.as_str(),
|
||||
)?) {
|
||||
TagType::Id3v2 => Ok(Box::new({
|
||||
let mut t = Id3v2Tag::read_from_path(path)?;
|
||||
t.set_config(self.config.clone());
|
||||
t
|
||||
})),
|
||||
TagType::Mp4 => Ok(Box::new({
|
||||
let mut t = Mp4Tag::read_from_path(path)?;
|
||||
t.set_config(self.config.clone());
|
||||
t
|
||||
})),
|
||||
TagType::Flac => Ok(Box::new({
|
||||
let mut t = FlacTag::read_from_path(path)?;
|
||||
t.set_config(self.config.clone());
|
||||
t
|
||||
})),
|
||||
}
|
||||
}
|
||||
/// Convert a concrete tag type into another
|
||||
#[macro_export]
|
||||
macro_rules! convert {
|
||||
($inp:expr, $target_type:ty) => {
|
||||
$target_type::from(inp.to_anytag())
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::*;
|
||||
|
||||
pub trait AudioTag: AudioTagEdit + AudioTagWrite + IntoAnyTag {}
|
||||
pub trait AudioTag: AudioTagEdit + AudioTagWrite + ToAnyTag {}
|
||||
|
||||
// pub trait TagIo {
|
||||
// fn read_from_path(path: &str) -> crate::Result<AnyTag>;
|
||||
|
@ -137,32 +137,22 @@ pub trait AudioTagConfig {
|
|||
fn set_config(&mut self, config: Config);
|
||||
}
|
||||
|
||||
pub trait IntoAnyTag {
|
||||
fn into_anytag(&self) -> AnyTag<'_>;
|
||||
pub trait ToAnyTag: ToAny {
|
||||
fn to_anytag(&self) -> AnyTag<'_>;
|
||||
|
||||
/// Convert the tag type, which can be lossy.
|
||||
fn into_tag(&self, tag_type: TagType) -> Box<dyn AudioTag> {
|
||||
fn to_dyn_tag(&self, tag_type: TagType) -> Box<dyn AudioTag> {
|
||||
// TODO: write a macro or something that implement this method for every tag type so that if the
|
||||
// TODO: target type is the same, just return self
|
||||
match tag_type {
|
||||
TagType::Id3v2 => Box::new(Id3v2Tag::from(self.into_anytag())),
|
||||
TagType::Mp4 => Box::new(Mp4Tag::from(self.into_anytag())),
|
||||
TagType::Flac => Box::new(FlacTag::from(self.into_anytag())),
|
||||
TagType::Id3v2 => Box::new(Id3v2Tag::from(self.to_anytag())),
|
||||
TagType::Mp4 => Box::new(Mp4Tag::from(self.to_anytag())),
|
||||
TagType::Flac => Box::new(FlacTag::from(self.to_anytag())),
|
||||
}
|
||||
}
|
||||
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()
|
||||
// }
|
||||
// }
|
||||
pub trait ToAny {
|
||||
fn to_any(&self) -> &dyn std::any::Any;
|
||||
fn to_any_mut(&mut self) -> &mut dyn std::any::Any;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ fn test_inner() {
|
|||
.vorbis_comments_mut()
|
||||
.set_title(vec!["title from metaflac::Tag"]);
|
||||
let tag: FlacTag = innertag.into();
|
||||
let mut id3tag = tag.into_tag(TagType::Id3v2);
|
||||
let mut id3tag = tag.to_dyn_tag(TagType::Id3v2);
|
||||
id3tag
|
||||
.write_to_path("assets/a.mp3")
|
||||
.expect("Fail to write!");
|
||||
|
|
Loading…
Reference in a new issue