cargo_toml_builder/
lib.rs

1//! Cargo.toml Builder
2//!
3//! Programmatically create Cargo.toml files
4//!
5//! # Example
6//!
7//! ```rust
8//! extern crate cargo_toml_builder;
9//!
10//! use cargo_toml_builder::prelude::*;
11//! # use std::error::Error;
12//! # fn main() -> Result<(), Box<dyn Error>> {
13//! let cargo_toml = CargoToml::builder()
14//!                     .name("my-project")
15//!                     .version("1.0.0")
16//!                     .author("Alice Smith <asmith@example.com>")
17//!                     .dependency("env_logger".version("0.5.6"))
18//!                     .build()?;
19//! assert_eq!(cargo_toml.to_string(), r#"
20//! [package]
21//! name = "my-project"
22//! version = "1.0.0"
23//! authors = ["Alice Smith <asmith@example.com>"]
24//!
25//! [dependencies]
26//! env_logger = "0.5.6"
27//! "#);
28//! #   Ok(())
29//! # }
30//! ```
31#![deny(
32    missing_docs,
33    missing_debug_implementations,
34    missing_copy_implementations,
35    trivial_casts,
36    trivial_numeric_casts,
37    unsafe_code,
38    unstable_features,
39    unused_import_braces,
40    unused_qualifications,
41    rust_2018_compatibility,
42    rust_2018_idioms
43    )]
44extern crate toml_edit;
45
46use std::collections::HashMap;
47use std::default::Default;
48
49use toml_edit::Document;
50
51use crate::toml::TomlOutput;
52use crate::types::*;
53use crate::types::Dependency;
54
55pub use crate::error::Error;
56
57/// Includes all types used by the builder
58pub mod types;
59mod toml;
60mod error;
61
62/// Use the glob import from this module to pull in the most common traits & types needed to work
63/// with the builder
64pub mod prelude {
65    pub use crate::CargoToml;
66    pub use crate::types::{BinTarget, BenchTarget, Dependency, DependencyExt, ExampleTarget, Feature, LibTarget, License, Profile, TestTarget};
67}
68
69/// Main builder struct
70///
71/// This is the builder that all other methods are called on. You can use `::builder()`,
72/// `::new()`, or `::default()` to get an initialized instance
73///
74/// # Example
75///
76/// ```
77/// extern crate cargo_toml_builder;
78/// use cargo_toml_builder::prelude::*;
79/// # use std::error::Error;
80/// # fn main() -> Result<(), Box<dyn Error>> {
81/// let cargo_toml = CargoToml::builder()
82///                     .name("my-project")
83///                     .author("Me <me@me.com>")
84///                     .build()?;
85///
86/// assert_eq!(cargo_toml.to_string(), r#"
87/// [package]
88/// name = "my-project"
89/// version = "0.1.0"
90/// authors = ["Me <me@me.com>"]
91///
92/// [dependencies]
93/// "#);
94/// #   Ok(())
95/// # }
96/// ```
97#[derive(Debug, Clone, PartialEq, Default)]
98pub struct CargoToml {
99    // [package]
100    /// The name that will be used for this Cargo.toml
101    pub name: Option<String>,
102    /// The list of authors that will be used for this Cargo.toml
103    pub authors: Option<Vec<String>>,
104    version: Option<String>,
105    build_script: Option<String>,
106    documentation: Option<String>,
107    exclude: Option<Vec<String>>,
108    include: Option<Vec<String>>,
109    publish: Option<bool>,
110    workspace_root: Option<String>,
111    description: Option<String>,
112    homepage: Option<String>,
113    repository: Option<String>,
114    readme: Option<String>,
115    keywords: Option<Vec<String>>,
116    categories: Option<Vec<String>>,
117    licenses: Option<Vec<License>>,
118    license_file: Option<String>,
119
120    // [badges]
121    appveyor: Option<Appveyor>,
122    circle_ci: Option<CircleCi>,
123    gitlab: Option<Gitlab>,
124    travis_ci: Option<TravisCi>,
125    codecov: Option<Codecov>,
126    coveralls: Option<Coveralls>,
127    is_it_maintained_time: Option<String>,
128    is_it_maintained_issues: Option<String>,
129    maintenance: Option<Maintenance>,
130
131    // [package.metadata]
132    metadata: Option<Vec<MetadataTable>>,
133
134    // [dependencies]
135    dependencies: Option<Vec<Dependency>>,
136
137    // [dev-dependencies]
138    dev_dependencies: Option<Vec<Dependency>>,
139
140    // [build-dependencies]
141    build_dependencies: Option<Vec<Dependency>>,
142
143    // [target.*.dependencies]
144    target_dependencies: Option<HashMap<String, Vec<Dependency>>>,
145
146    // [profile.*]
147    profile_dev: Option<Profile>,
148    profile_release: Option<Profile>,
149    profile_test: Option<Profile>,
150    profile_bench: Option<Profile>,
151    profile_doc: Option<Profile>,
152
153    // [features]
154    features: Option<Vec<Feature>>,
155
156    // [workspace]
157    workspace: Option<Workspace>,
158
159    // [[bin]]
160    bins: Option<Vec<BinTarget>>,
161
162    // [lib]
163    lib: Option<LibTarget>,
164
165    // [[bench]]
166    benches: Option<Vec<BenchTarget>>,
167
168    // [[test]]
169    tests: Option<Vec<TestTarget>>,
170
171    // [[example]]
172    examples: Option<Vec<ExampleTarget>>,
173
174    // [patch.*]
175    patches: Option<Vec<PatchSet>>,
176
177    // [replace]
178    replacements: Option<Vec<Replace>>,
179}
180
181impl CargoToml {
182    /// Construct a new instance
183    ///
184    /// # Example
185    ///
186    /// ```rust
187    /// extern crate cargo_toml_builder;
188    /// use cargo_toml_builder::CargoToml;
189    /// # use std::error::Error;
190    /// # fn main() -> Result<(), Box<dyn Error>> {
191    /// let cargo_toml = CargoToml::new();
192    /// #   Ok(())
193    /// # }
194    /// ```
195    pub fn new() -> CargoToml {
196        Default::default()
197    }
198
199    /// Construct a new instance
200    ///
201    /// # Example
202    ///
203    /// ```rust
204    /// extern crate cargo_toml_builder;
205    /// use cargo_toml_builder::CargoToml;
206    /// # use std::error::Error;
207    /// # fn main() -> Result<(), Box<dyn Error>> {
208    /// let cargo_toml = CargoToml::builder();
209    /// #   Ok(())
210    /// # }
211    /// ```
212    pub fn builder() -> CargoToml {
213        Default::default()
214    }
215
216    /// Sets the `package.name` of the project
217    ///
218    /// # Example
219    ///
220    /// ```rust
221    /// extern crate cargo_toml_builder;
222    /// use cargo_toml_builder::CargoToml;
223    /// # use std::error::Error;
224    /// # fn main() -> Result<(), Box<dyn Error>> {
225    /// let cargo_toml = CargoToml::new()
226    ///                     .name("my-rust-project")
227    /// #                   .author("me")
228    ///                     .build()?;
229    /// # assert!(cargo_toml.to_string().contains(r#"name = "my-rust-project""#));
230    /// /*
231    /// [package]
232    /// name = "my-rust-project"
233    /// */
234    /// #   Ok(())
235    /// # }
236    /// ```
237    pub fn name(&mut self, name: &str) -> &mut Self {
238        self.name = Some(name.to_string());
239        self
240    }
241
242    /// Add an author to the `package.authors` property
243    ///
244    /// Note: This will append an entry to the underlying Vec, it will not affect any other
245    /// `author`s that have been set
246    ///
247    /// # Example
248    ///
249    /// ```rust
250    /// extern crate cargo_toml_builder;
251    /// use cargo_toml_builder::prelude::*;
252    /// # use std::error::Error;
253    /// # fn main() -> Result<(), Box<dyn Error>> {
254    /// let cargo_toml = CargoToml::new()
255    ///                     .author("Me <me@me.com>")
256    /// #                   .name("my-project")
257    ///                     .build()?;
258    /// # assert!(cargo_toml.to_string().contains(r#"authors = ["Me <me@me.com>"]"#));
259    /// /*
260    /// [package]
261    /// authors = ["Me <me@me.com>"]
262    /// */
263    /// #   Ok(())
264    /// # }
265    /// ```
266    pub fn author(&mut self, author: &str) -> &mut Self {
267        if let Some(ref mut v) = self.authors {
268            v.push(author.to_string());
269        } else {
270            self.authors = Some(vec![author.to_string()]);
271        }
272        self
273    }
274
275    /// Set the list of authors for the `package.authors` property
276    ///
277    /// Note: This will _replace_ any existing list of authors
278    ///
279    /// # Example
280    ///
281    /// ```rust
282    /// extern crate cargo_toml_builder;
283    /// use cargo_toml_builder::prelude::*;
284    /// # use std::error::Error;
285    /// # fn main() -> Result<(), Box<dyn Error>> {
286    /// let cargo_toml = CargoToml::new()
287    ///                     .authors(&[
288    ///                         "Me <me@me.com>".into(),
289    ///                         "You <you@you.com>".into()
290    ///                     ])
291    /// #                   .name("my-project")
292    ///                     .build()?;
293    /// # assert!(cargo_toml.to_string().contains(r#"authors = ["Me <me@me.com>", "You <you@you.com>"]"#));
294    /// /*
295    /// [package]
296    /// authors = ["Me <me@me.com>", "You <you@you.com>"]
297    /// */
298    /// #   Ok(())
299    /// # }
300    /// ```
301    pub fn authors(&mut self, authors: &[String]) -> &mut Self {
302        self.authors = Some(authors.to_vec());
303        self
304    }
305
306    /// Sets the `package.version` of the project
307    ///
308    /// # Example
309    ///
310    /// ```rust
311    /// extern crate cargo_toml_builder;
312    /// use cargo_toml_builder::prelude::*;
313    /// # use std::error::Error;
314    /// # fn main() -> Result<(), Box<dyn Error>> {
315    /// let cargo_toml = CargoToml::new()
316    ///                         .version("1.1.0")
317    /// #                       .author("me")
318    /// #                       .name("my-project")
319    ///                         .build()?;
320    /// # assert!(cargo_toml.to_string().contains(r#"version = "1.1.0""#));
321    /// /*
322    /// [package]
323    /// version = "1.1.0"
324    /// */
325    /// #   Ok(())
326    /// # }
327    /// ```
328    pub fn version(&mut self, version: &str) -> &mut Self {
329        self.version = Some(version.into());
330        self
331    }
332
333    /// Sets the `package.build` property of the project
334    ///
335    /// TODO: currently impossible to generate `build = false`
336    ///
337    /// # Example
338    ///
339    /// ```rust
340    /// extern crate cargo_toml_builder;
341    /// use cargo_toml_builder::prelude::*;
342    /// # use std::error::Error;
343    /// # fn main() -> Result<(), Box<dyn Error>> {
344    ///
345    /// let cargo_toml = CargoToml::new()
346    ///                     .build_script("./my-build-script.rs")
347    /// #                   .author("me")
348    /// #                   .name("my-project")
349    ///                     .build()?;
350    /// # assert!(cargo_toml.to_string().contains(r#"build = "./my-build-script.rs""#));
351    /// /*
352    /// [package]
353    /// build = "./my-build-script"
354    /// */
355    /// #   Ok(())
356    /// # }
357    /// ```
358    pub fn build_script(&mut self, build: &str) -> &mut Self {
359        self.build_script = Some(build.into());
360        self
361    }
362
363    /// Sets the `package.documentation` property of the project
364    ///
365    /// # Example
366    ///
367    /// ```rust
368    /// extern crate cargo_toml_builder;
369    /// use cargo_toml_builder::prelude::*;
370    /// # use std::error::Error;
371    /// # fn main() -> Result<(), Box<dyn Error>> {
372    /// let cargo_toml = CargoToml::new()
373    ///                     .documentation("https://docs.rs/my-project")
374    /// #                   .author("me")
375    /// #                   .name("my-project")
376    ///                     .build()?;
377    /// # assert!(cargo_toml.to_string().contains(r#"documentation = "https://docs.rs/my-project""#));
378    /// /*
379    /// [package]
380    /// documentation = "https://docs.rs/my-project"
381    /// */
382    /// #   Ok(())
383    /// # }
384    /// ```
385    pub fn documentation(&mut self, documentation: &str) -> &mut Self {
386        self.documentation = Some(documentation.into());
387        self
388    }
389
390    /// Adds an exclusion pattern to the `package.exclude` property
391    ///
392    /// # Example
393    ///
394    /// ```rust
395    /// extern crate cargo_toml_builder;
396    ///
397    /// use cargo_toml_builder::prelude::*;
398    /// # use std::error::Error;
399    /// # fn main() -> Result<(), Box<dyn Error>> {
400    ///
401    /// let cargo_toml = CargoToml::new()
402    ///                     .exclude("build/**/*.o")
403    /// #                   .author("me")
404    /// #                   .name("my-project")
405    ///                     .build()?;
406    /// # assert!(cargo_toml.to_string().contains(r#"exclude = ["build/**/*.o"]"#));
407    /// /*
408    /// [package]
409    /// exclude = ["build/**/*.o"]
410    /// */
411    /// #   Ok(())
412    /// # }
413    /// ```
414    pub fn exclude(&mut self, exclude: &str) -> &mut Self {
415        if let Some(ref mut v) = self.exclude {
416            v.push(exclude.into());
417        } else {
418            self.exclude = Some(vec![exclude.into()]);
419        }
420        self
421    }
422
423    /// Sets the list of exclusion patterns for the `package.exclude` property
424    ///
425    /// # Example
426    ///
427    /// ```rust
428    /// extern crate cargo_toml_builder;
429    ///
430    /// use cargo_toml_builder::prelude::*;
431    /// # use std::error::Error;
432    /// # fn main() -> Result<(), Box<dyn Error>> {
433    ///
434    /// let cargo_toml = CargoToml::new()
435    ///                     .excludes(&[
436    ///                         "build/**/*.o".into(),
437    ///                         "doc/**/*.html".into(),
438    ///                     ])
439    /// #                   .author("me")
440    /// #                   .name("my-project")
441    ///                     .build()?;
442    /// # assert!(cargo_toml.to_string().contains(r#"exclude = ["build/**/*.o", "doc/**/*.html"]"#));
443    /// /*
444    /// [package]
445    /// exclude = ["build/**/*.o", "doc/**/*.html"]
446    /// */
447    /// #   Ok(())
448    /// # }
449    /// ```
450    pub fn excludes(&mut self, excludes: &[String]) -> &mut Self {
451        self.exclude = Some(excludes.to_vec());
452        self
453    }
454
455    /// Adds an inclusion pattern to the `package.include` property
456    ///
457    /// # Example
458    ///
459    /// ```rust
460    /// extern crate cargo_toml_builder;
461    ///
462    /// use cargo_toml_builder::prelude::*;
463    /// # use std::error::Error;
464    /// # fn main() -> Result<(), Box<dyn Error>> {
465    ///
466    /// let cargo_toml = CargoToml::new()
467    ///                     .include("src/**/*")
468    /// #                   .author("me")
469    /// #                   .name("my-project")
470    ///                     .build()?;
471    /// # assert!(cargo_toml.to_string().contains(r#"include = ["src/**/*"]"#));
472    /// /*
473    /// [package]
474    /// include = ["src/**/*"]
475    /// */
476    /// #   Ok(())
477    /// # }
478    /// ```
479    pub fn include(&mut self, include: &str) -> &mut Self {
480        if let Some(ref mut v) = self.include {
481            v.push(include.into());
482        } else {
483            self.include = Some(vec![include.into()]);
484        }
485        self
486    }
487
488    /// Sets the inclusion patterns for the `package.include` property
489    ///
490    /// # Example
491    ///
492    /// ```rust
493    /// extern crate cargo_toml_builder;
494    ///
495    /// use cargo_toml_builder::prelude::*;
496    /// # use std::error::Error;
497    /// # fn main() -> Result<(), Box<dyn Error>> {
498    ///
499    /// let cargo_toml = CargoToml::new()
500    ///                     .includes(&[
501    ///                         "src/**/*".into(),
502    ///                         "Cargo.toml".into(),
503    ///                     ])
504    /// #                   .author("me")
505    /// #                   .name("my-project")
506    ///                     .build()?;
507    /// # assert!(cargo_toml.to_string().contains(r#"include = ["src/**/*", "Cargo.toml"]"#));
508    /// /*
509    /// [package]
510    /// include = ["src/**/*.html, "Cargo.toml"]
511    /// */
512    /// #   Ok(())
513    /// # }
514    /// ```
515    pub fn includes(&mut self, includes: &[String]) -> &mut Self {
516        self.include = Some(includes.to_vec());
517        self
518    }
519
520    /// Sets the `package.publish` property
521    ///
522    /// # Example
523    ///
524    /// ```rust
525    /// extern crate cargo_toml_builder;
526    ///
527    /// use cargo_toml_builder::prelude::*;
528    /// # use std::error::Error;
529    /// # fn main() -> Result<(), Box<dyn Error>> {
530    ///
531    /// let cargo_toml = CargoToml::new()
532    ///                     .publish(false)
533    /// #                   .author("me")
534    /// #                   .name("my-project")
535    ///                     .build()?;
536    /// # assert!(cargo_toml.to_string().contains(r#"publish = false"#));
537    /// /*
538    /// [package]
539    /// publish = false
540    /// */
541    /// #   Ok(())
542    /// # }
543    /// ```
544    pub fn publish(&mut self, publish: bool) -> &mut Self {
545        self.publish = Some(publish);
546        self
547    }
548
549    /// Sets the `package.workspace` property
550    ///
551    /// (this is the `workspace = "/path/to/workspace"` property, not be be confused with the
552    /// `[workspace]` table that can also be added to the document)
553    ///
554    /// # Example
555    ///
556    /// ```rust
557    /// extern crate cargo_toml_builder;
558    ///
559    /// use cargo_toml_builder::prelude::*;
560    /// # use std::error::Error;
561    /// # fn main() -> Result<(), Box<dyn Error>> {
562    ///
563    /// let cargo_toml = CargoToml::new()
564    ///                     .workspace_root("/path/to/workspace/root")
565    /// #                   .author("me")
566    /// #                   .name("my-project")
567    ///                     .build()?;
568    /// # assert!(cargo_toml.to_string().contains(r#"workspace = "/path/to/workspace/root""#));
569    /// /*
570    /// [package]
571    /// workspace = "/path/to/workspace/root"
572    /// */
573    /// #   Ok(())
574    /// # }
575    /// ```
576    pub fn workspace_root(&mut self, workspace_root: &str) -> &mut Self {
577        self.workspace_root = Some(workspace_root.into());
578        self
579    }
580
581    /// Sets the `package.description` property
582    ///
583    /// # Example
584    ///
585    /// ```rust
586    /// extern crate cargo_toml_builder;
587    ///
588    /// use cargo_toml_builder::prelude::*;
589    /// # use std::error::Error;
590    /// # fn main() -> Result<(), Box<dyn Error>> {
591    ///
592    /// let cargo_toml = CargoToml::new()
593    ///                     .description("This is my new Rust project")
594    /// #                   .author("me")
595    /// #                   .name("my-project")
596    ///                     .build()?;
597    /// # assert!(cargo_toml.to_string().contains(r#"description = "This is my new Rust project""#));
598    /// /*
599    /// [package]
600    /// description = "This is my new Rust project"
601    /// */
602    /// #   Ok(())
603    /// # }
604    /// ```
605    pub fn description(&mut self, description: &str) -> &mut Self {
606        self.description = Some(description.into());
607        self
608    }
609
610    /// Sets the `package.homepage` property
611    ///
612    /// # Example
613    ///
614    /// ```rust
615    /// extern crate cargo_toml_builder;
616    ///
617    /// use cargo_toml_builder::prelude::*;
618    /// # use std::error::Error;
619    /// # fn main() -> Result<(), Box<dyn Error>> {
620    ///
621    /// let cargo_toml = CargoToml::new()
622    ///                     .homepage("https://my.domain/")
623    /// #                   .author("me")
624    /// #                   .name("my-project")
625    ///                     .build()?;
626    /// # assert!(cargo_toml.to_string().contains(r#"homepage = "https://my.domain/""#));
627    /// /*
628    /// [package]
629    /// homepage = "https://my.domain/"
630    /// */
631    /// #   Ok(())
632    /// # }
633    /// ```
634    pub fn homepage(&mut self, homepage: &str) -> &mut Self {
635        self.homepage = Some(homepage.into());
636        self
637    }
638
639    /// Sets the `package.repository` property
640    ///
641    /// # Example
642    ///
643    /// ```rust
644    /// extern crate cargo_toml_builder;
645    ///
646    /// use cargo_toml_builder::prelude::*;
647    /// # use std::error::Error;
648    /// # fn main() -> Result<(), Box<dyn Error>> {
649    ///
650    /// let cargo_toml = CargoToml::new()
651    ///                     .repository("https://gitlab.com/me/my-project")
652    /// #                   .author("me")
653    /// #                   .name("my-project")
654    ///                     .build()?;
655    /// # assert!(cargo_toml.to_string().contains(r#"repository = "https://gitlab.com/me/my-project""#));
656    /// /*
657    /// [package]
658    /// repository = "https://gitlab.com/me/my-project"
659    /// */
660    /// #   Ok(())
661    /// # }
662    /// ```
663    pub fn repository(&mut self, repository: &str) -> &mut Self {
664        self.repository = Some(repository.into());
665        self
666    }
667
668    /// Sets the `package.readme` property
669    ///
670    /// # Example
671    ///
672    /// ```rust
673    /// extern crate cargo_toml_builder;
674    ///
675    /// use cargo_toml_builder::prelude::*;
676    /// # use std::error::Error;
677    /// # fn main() -> Result<(), Box<dyn Error>> {
678    ///
679    /// let cargo_toml = CargoToml::new()
680    ///                     .readme("README.adoc")
681    /// #                   .author("me")
682    /// #                   .name("my-project")
683    ///                     .build()?;
684    /// # assert!(cargo_toml.to_string().contains(r#"readme = "README.adoc""#));
685    /// /*
686    /// [package]
687    /// readme = "README.adoc"
688    /// */
689    /// #   Ok(())
690    /// # }
691    /// ```
692    pub fn readme(&mut self, readme: &str) -> &mut Self {
693        self.readme = Some(readme.into());
694        self
695    }
696
697    /// Adds a keyword to the `package.keywords` property
698    ///
699    /// # Example
700    ///
701    /// ```rust
702    /// extern crate cargo_toml_builder;
703    ///
704    /// use cargo_toml_builder::prelude::*;
705    /// # use std::error::Error;
706    /// # fn main() -> Result<(), Box<dyn Error>> {
707    ///
708    /// let cargo_toml = CargoToml::new()
709    ///                     .keyword("async")
710    /// #                   .author("me")
711    /// #                   .name("my-project")
712    ///                     .build()?;
713    /// # assert!(cargo_toml.to_string().contains(r#"keywords = ["async"]"#));
714    /// /*
715    /// [package]
716    /// keywords = ["async"]
717    /// */
718    /// #   Ok(())
719    /// # }
720    /// ```
721    pub fn keyword(&mut self, keyword: &str) -> &mut Self {
722        if let Some(ref mut v) = self.keywords {
723            v.push(keyword.into());
724        } else {
725            self.keywords = Some(vec![keyword.into()]);
726        }
727        self
728    }
729
730    /// Sets the list of keywords for the `package.keywords` property
731    ///
732    /// # Example
733    ///
734    /// ```rust
735    /// extern crate cargo_toml_builder;
736    ///
737    /// use cargo_toml_builder::prelude::*;
738    /// # use std::error::Error;
739    /// # fn main() -> Result<(), Box<dyn Error>> {
740    ///
741    /// let cargo_toml = CargoToml::new()
742    ///                     .keywords(&[
743    ///                         "async".into(),
744    ///                         "networking".into(),
745    ///                     ])
746    /// #                   .author("me")
747    /// #                   .name("my-project")
748    ///                     .build()?;
749    /// # assert!(cargo_toml.to_string().contains(r#"keywords = ["async", "networking"]"#));
750    /// /*
751    /// [package]
752    /// keywords = ["async", "networking"]
753    /// */
754    /// #   Ok(())
755    /// # }
756    /// ```
757    pub fn keywords(&mut self, keywords: &[String]) -> &mut Self {
758        self.keywords = Some(keywords.to_vec());
759        self
760    }
761
762    /// Adds a category to the `package.categories` property
763    ///
764    /// # Example
765    ///
766    /// ```rust
767    /// extern crate cargo_toml_builder;
768    ///
769    /// use cargo_toml_builder::prelude::*;
770    /// # use std::error::Error;
771    /// # fn main() -> Result<(), Box<dyn Error>> {
772    ///
773    /// let cargo_toml = CargoToml::new()
774    ///                     .category("filesystem")
775    /// #                   .author("me")
776    /// #                   .name("my-project")
777    ///                     .build()?;
778    /// # assert!(cargo_toml.to_string().contains(r#"categories = ["filesystem"]"#));
779    /// /*
780    /// [package]
781    /// categories = ["filesystem"]
782    /// */
783    /// #   Ok(())
784    /// # }
785    /// ```
786    pub fn category(&mut self, category: &str) -> &mut Self {
787        if let Some(ref mut v) = self.categories {
788            v.push(category.into());
789        } else {
790            self.categories = Some(vec![category.into()]);
791        }
792        self
793    }
794
795    /// Sets the list of categories for the `package.categories` property
796    ///
797    /// # Example
798    ///
799    /// ```rust
800    /// extern crate cargo_toml_builder;
801    ///
802    /// use cargo_toml_builder::prelude::*;
803    /// # use std::error::Error;
804    /// # fn main() -> Result<(), Box<dyn Error>> {
805    ///
806    /// let cargo_toml = CargoToml::new()
807    ///                     .categories(&[
808    ///                         "filesystem".into(),
809    ///                         "testing".into(),
810    ///                     ])
811    /// #                   .author("me")
812    /// #                   .name("my-project")
813    ///                     .build()?;
814    /// # assert!(cargo_toml.to_string().contains(r#"categories = ["filesystem", "testing"]"#));
815    /// /*
816    /// [package]
817    /// categories = ["filesystem", "testing"]
818    /// */
819    /// #   Ok(())
820    /// # }
821    /// ```
822    pub fn categories(&mut self, categories: &[String]) -> &mut Self {
823        self.categories = Some(categories.to_vec());
824        self
825    }
826
827    /// Adds a license to the project
828    ///
829    /// # Example
830    ///
831    /// ```rust
832    /// extern crate cargo_toml_builder;
833    ///
834    /// use cargo_toml_builder::prelude::*;
835    /// # use std::error::Error;
836    /// # fn main() -> Result<(), Box<dyn Error>> {
837    ///
838    /// let cargo_toml = CargoToml::new()
839    ///                     .license(License::Mit)
840    /// #                   .author("me")
841    /// #                   .name("my-project")
842    ///                     .build()?;
843    /// # assert!(cargo_toml.to_string().contains(r#"license = "MIT""#));
844    /// /*
845    /// [package]
846    /// license = "MIT"
847    /// */
848    /// #   Ok(())
849    /// # }
850    /// ```
851    pub fn license<L: Into<License>>(&mut self, license: L) -> &mut Self {
852        if let Some(ref mut v) = self.licenses {
853            v.push(license.into());
854        } else {
855            self.licenses = Some(vec![license.into()]);
856        }
857        self
858    }
859
860    /// Sets a list of licenses for the project
861    ///
862    /// # Example
863    ///
864    /// ```rust
865    /// extern crate cargo_toml_builder;
866    ///
867    /// use cargo_toml_builder::prelude::*;
868    /// # use std::error::Error;
869    /// # fn main() -> Result<(), Box<dyn Error>> {
870    ///
871    /// let cargo_toml = CargoToml::new()
872    ///                     .licenses(&[
873    ///                         License::Mit,
874    ///                         License::Apache2,
875    ///                     ])
876    /// #                   .author("me")
877    /// #                   .name("my-project")
878    ///                     .build()?;
879    /// # assert!(cargo_toml.to_string().contains(r#"license = "MIT/Apache-2.0""#));
880    /// /*
881    /// [package]
882    /// license = "MIT/Apache-2.0"
883    /// */
884    /// #   Ok(())
885    /// # }
886    /// ```
887    pub fn licenses<L: Into<License> + Clone>(&mut self, licenses: &[L]) -> &mut Self {
888        self.licenses = Some(licenses.to_vec().into_iter().map(|l| l.into()).collect::<Vec<_>>());
889        self
890    }
891
892    /// Sets the location for the license file of the project
893    ///
894    /// # Example
895    ///
896    /// ```rust
897    /// extern crate cargo_toml_builder;
898    ///
899    /// use cargo_toml_builder::prelude::*;
900    /// # use std::error::Error;
901    /// # fn main() -> Result<(), Box<dyn Error>> {
902    ///
903    /// let cargo_toml = CargoToml::new()
904    ///                     .license_file("LICENSE")
905    /// #                   .author("me")
906    /// #                   .name("my-project")
907    ///                     .build()?;
908    /// # assert!(cargo_toml.to_string().contains(r#"license-file = "LICENSE""#));
909    /// /*
910    /// [package]
911    /// license-file = "LICENSE"
912    /// */
913    /// #   Ok(())
914    /// # }
915    /// ```
916    pub fn license_file(&mut self, license_file: &str) -> &mut Self {
917        self.license_file = Some(license_file.into());
918        self
919    }
920
921    /// Sets the `badges.appveyor` table for the project
922    ///
923    /// You can import the "Appveyor" struct from `cargo_toml_builder::types`, but this method will
924    /// take anything that implements `Into<Appveyor>`, which `String` and `&str` do. So if all you
925    /// want is to add the repo, you can just pass some kind of string to this method and it should
926    /// Just Work.
927    ///
928    /// # Example
929    ///
930    /// ```rust
931    /// extern crate cargo_toml_builder;
932    ///
933    /// use cargo_toml_builder::prelude::*;
934    /// use cargo_toml_builder::types::Appveyor;
935    /// # use std::error::Error;
936    /// # fn main() -> Result<(), Box<dyn Error>> {
937    ///
938    /// let appveyor_badge = Appveyor::new("https://gitlab.com/me/my-project");
939    /// let cargo_toml = CargoToml::new()
940    ///                     .appveyor(appveyor_badge)
941    /// // or this will also work, and result in the same output:
942    /// //                  .appveyor("https://gitlab.com/me/my-project")
943    /// #                   .author("me")
944    /// #                   .name("my-project")
945    ///                     .build()?;
946    /// # assert!(cargo_toml.to_string().contains(r#"appveyor = {repository = "https://gitlab.com/me/my-project"}"#));
947    /// /*
948    /// [badges]
949    /// appveyor = { repository = "https://gitlab.com/me/my-project" }
950    /// */
951    /// #   Ok(())
952    /// # }
953    /// ```
954    pub fn appveyor<A: Into<Appveyor>>(&mut self, appveyor: A) -> &mut Self {
955        self.appveyor = Some(appveyor.into());
956        self
957    }
958
959    /// Sets the `badges.circle-ci` table for the project
960    ///
961    /// # Example
962    ///
963    /// ```rust
964    /// extern crate cargo_toml_builder;
965    ///
966    /// use cargo_toml_builder::prelude::*;
967    /// use cargo_toml_builder::types::CircleCi;
968    /// # use std::error::Error;
969    /// # fn main() -> Result<(), Box<dyn Error>> {
970    ///
971    /// let circe_ci_badge = CircleCi::new("https://gitlab.com/me/my-project");
972    /// let cargo_toml = CargoToml::new()
973    ///                     .circle_ci(circe_ci_badge)
974    /// #                   .author("me")
975    /// #                   .name("my-project")
976    ///                     .build()?;
977    /// # assert!(cargo_toml.to_string().contains(r#"circle-ci = {repository = "https://gitlab.com/me/my-project"}"#));
978    /// /*
979    /// [badges]
980    /// circle-ci = { repository = "https://gitlab.com/me/my-project" }
981    /// */
982    /// #   Ok(())
983    /// # }
984    /// ```
985    pub fn circle_ci<C: Into<CircleCi>>(&mut self, circle_ci: C) -> &mut Self {
986        self.circle_ci = Some(circle_ci.into());
987        self
988    }
989
990    /// Sets the `badges.gitlab` table for the project
991    ///
992    /// # Example
993    ///
994    /// ```rust
995    /// extern crate cargo_toml_builder;
996    ///
997    /// use cargo_toml_builder::prelude::*;
998    /// use cargo_toml_builder::types::Gitlab;
999    /// # use std::error::Error;
1000    /// # fn main() -> Result<(), Box<dyn Error>> {
1001    ///
1002    /// let gitlab_badge = Gitlab::new("https://gitlab.com/me/my-project");
1003    /// let cargo_toml = CargoToml::new()
1004    ///                     .gitlab(gitlab_badge)
1005    /// #                   .author("me")
1006    /// #                   .name("my-project")
1007    ///                     .build()?;
1008    /// # assert!(cargo_toml.to_string().contains(r#"gitlab = {repository = "https://gitlab.com/me/my-project"}"#));
1009    /// /*
1010    /// [badges]
1011    /// gitlab = { repository = "https://gitlab.com/me/my-project" }
1012    /// */
1013    /// #   Ok(())
1014    /// # }
1015    /// ```
1016    pub fn gitlab<G: Into<Gitlab>>(&mut self, gitlab: G) -> &mut Self {
1017        self.gitlab = Some(gitlab.into());
1018        self
1019    }
1020
1021    /// Sets the `badges.travis-ci` table for the project
1022    ///
1023    /// # Example
1024    ///
1025    /// ```rust
1026    /// extern crate cargo_toml_builder;
1027    ///
1028    /// use cargo_toml_builder::prelude::*;
1029    /// use cargo_toml_builder::types::TravisCi;
1030    /// # use std::error::Error;
1031    /// # fn main() -> Result<(), Box<dyn Error>> {
1032    ///
1033    /// let travis_ci_badge = TravisCi::new("https://gitlab.com/me/my-project");
1034    /// let cargo_toml = CargoToml::new()
1035    ///                     .travis_ci(travis_ci_badge)
1036    /// #                   .author("me")
1037    /// #                   .name("my-project")
1038    ///                     .build()?;
1039    /// # assert!(cargo_toml.to_string().contains(r#"travis-ci = {repository = "https://gitlab.com/me/my-project"}"#));
1040    /// /*
1041    /// [badges]
1042    /// travis-ci = { repository = "https://gitlab.com/me/my-project" }
1043    /// */
1044    /// #   Ok(())
1045    /// # }
1046    /// ```
1047    pub fn travis_ci<T: Into<TravisCi>>(&mut self, travis_ci: T) -> &mut Self {
1048        self.travis_ci = Some(travis_ci.into());
1049        self
1050    }
1051
1052    /// Sets the `badges.codecov` table for the project
1053    ///
1054    /// # Example
1055    ///
1056    /// ```rust
1057    /// extern crate cargo_toml_builder;
1058    ///
1059    /// use cargo_toml_builder::prelude::*;
1060    /// use cargo_toml_builder::types::Codecov;
1061    /// # use std::error::Error;
1062    /// # fn main() -> Result<(), Box<dyn Error>> {
1063    ///
1064    /// let codecov_badge = Codecov::new("https://gitlab.com/me/my-project");
1065    /// let cargo_toml = CargoToml::new()
1066    ///                     .codecov(codecov_badge)
1067    /// #                   .author("me")
1068    /// #                   .name("my-project")
1069    ///                     .build()?;
1070    /// # assert!(cargo_toml.to_string().contains(r#"codecov = {repository = "https://gitlab.com/me/my-project"}"#));
1071    /// /*
1072    /// [badges]
1073    /// codecov = { repository = "https://gitlab.com/me/my-project" }
1074    /// */
1075    /// #   Ok(())
1076    /// # }
1077    /// ```
1078    pub fn codecov<C: Into<Codecov>>(&mut self, codecov: C) -> &mut Self {
1079        self.codecov = Some(codecov.into());
1080        self
1081    }
1082
1083    /// Sets the `badges.coveralls` table for the project
1084    ///
1085    /// # Example
1086    ///
1087    /// ```rust
1088    /// extern crate cargo_toml_builder;
1089    ///
1090    /// use cargo_toml_builder::prelude::*;
1091    /// use cargo_toml_builder::types::Coveralls;
1092    /// # use std::error::Error;
1093    /// # fn main() -> Result<(), Box<dyn Error>> {
1094    ///
1095    /// let coveralls_badge = Coveralls::new("https://gitlab.com/me/my-project");
1096    /// let cargo_toml = CargoToml::new()
1097    ///                     .coveralls(coveralls_badge)
1098    /// #                   .author("me")
1099    /// #                   .name("my-project")
1100    ///                     .build()?;
1101    /// # assert!(cargo_toml.to_string().contains(r#"coveralls = {repository = "https://gitlab.com/me/my-project"}"#));
1102    /// /*
1103    /// [badges]
1104    /// coveralls = { repository = "https://gitlab.com/me/my-project" }
1105    /// */
1106    /// #   Ok(())
1107    /// # }
1108    /// ```
1109    pub fn coveralls<C: Into<Coveralls>>(&mut self, coveralls: C) -> &mut Self {
1110        self.coveralls = Some(coveralls.into());
1111        self
1112    }
1113
1114    /// Sets the `badges.is-it-maintained-issue-resolution` table for the project
1115    ///
1116    /// # Example
1117    ///
1118    /// ```rust
1119    /// extern crate cargo_toml_builder;
1120    ///
1121    /// use cargo_toml_builder::prelude::*;
1122    /// use cargo_toml_builder::types::Coveralls;
1123    /// # use std::error::Error;
1124    /// # fn main() -> Result<(), Box<dyn Error>> {
1125    ///
1126    /// let cargo_toml = CargoToml::new()
1127    ///                     .is_it_maintained_time("https://gitlab.com/me/my-project")
1128    /// #                   .author("me")
1129    /// #                   .name("my-project")
1130    ///                     .build()?;
1131    /// # assert!(cargo_toml.to_string().contains(r#"is-it-maintained-issue-resolution = {repository = "https://gitlab.com/me/my-project"}"#));
1132    /// /*
1133    /// [badges]
1134    /// is-it-maintained-issue-resolution = { repository = "https://gitlab.com/me/my-project" }
1135    /// */
1136    /// #   Ok(())
1137    /// # }
1138    /// ```
1139    pub fn is_it_maintained_time(&mut self, time: &str) -> &mut Self {
1140        self.is_it_maintained_time = Some(time.into());
1141        self
1142    }
1143
1144    /// Sets the `badges.is-it-maintained-open-issues` table for the project
1145    ///
1146    /// # Example
1147    ///
1148    /// ```rust
1149    /// extern crate cargo_toml_builder;
1150    ///
1151    /// use cargo_toml_builder::prelude::*;
1152    /// use cargo_toml_builder::types::Coveralls;
1153    /// # use std::error::Error;
1154    /// # fn main() -> Result<(), Box<dyn Error>> {
1155    ///
1156    /// let cargo_toml = CargoToml::new()
1157    ///                     .is_it_maintained_issues("https://gitlab.com/me/my-project")
1158    /// #                   .author("me")
1159    /// #                   .name("my-project")
1160    ///                     .build()?;
1161    /// # assert!(cargo_toml.to_string().contains(r#"is-it-maintained-open-issues = {repository = "https://gitlab.com/me/my-project"}"#));
1162    /// /*
1163    /// [badges]
1164    /// is-it-maintained-open-issues = { repository = "https://gitlab.com/me/my-project" }
1165    /// */
1166    /// #   Ok(())
1167    /// # }
1168    /// ```
1169    pub fn is_it_maintained_issues(&mut self, issues: &str) -> &mut Self {
1170        self.is_it_maintained_issues = Some(issues.into());
1171        self
1172    }
1173
1174    /// Sets the `badges.maintenance` table for the project
1175    ///
1176    /// # Example
1177    ///
1178    /// ```rust
1179    /// extern crate cargo_toml_builder;
1180    ///
1181    /// use cargo_toml_builder::prelude::*;
1182    /// use cargo_toml_builder::types::MaintenanceStatus;
1183    /// # use std::error::Error;
1184    /// # fn main() -> Result<(), Box<dyn Error>> {
1185    ///
1186    /// let cargo_toml = CargoToml::new()
1187    ///                     .maintenance(MaintenanceStatus::AsIs)
1188    /// #                   .author("me")
1189    /// #                   .name("my-project")
1190    ///                     .build()?;
1191    /// # assert!(cargo_toml.to_string().contains(r#"maintenance = {status = "as-is"}"#));
1192    /// /*
1193    /// [badges]
1194    /// maintenance = { status = "as-is" }
1195    /// */
1196    /// #   Ok(())
1197    /// # }
1198    /// ```
1199    pub fn maintenance<M: Into<MaintenanceStatus>>(&mut self, maintenance: M) -> &mut Self {
1200        self.maintenance = Some(Maintenance::from(maintenance.into()));
1201        self
1202    }
1203
1204    /// Adds a dependency to the `dependencies` table
1205    ///
1206    /// The `Dependency` struct is imported through the prelude, but you can also pass anything to
1207    /// this that implements `Into<Dependency>` which `String` and `&str` do. If you pass a string
1208    /// to this method, it will add a regular crate dependency, with version `"*"`. You can use the
1209    /// extension methods from [`DependencyExt`](./types/trait.DependencyExt.html) to use a string to
1210    /// construct a `Dependency` object.
1211    ///
1212    /// # Example
1213    ///
1214    /// ```rust
1215    /// extern crate cargo_toml_builder;
1216    ///
1217    /// use cargo_toml_builder::prelude::*;
1218    /// # use std::error::Error;
1219    /// # fn main() -> Result<(), Box<dyn Error>> {
1220    ///
1221    /// let cargo_toml = CargoToml::new()
1222    ///                     .dependency("env_logger".version("0.5.6"))
1223    /// #                   .author("me")
1224    /// #                   .name("my-project")
1225    ///                     .build()?;
1226    /// # assert!(cargo_toml.to_string().contains(r#"[dependencies]"#));
1227    /// # assert!(cargo_toml.to_string().contains(r#"env_logger = "0.5.6""#));
1228    /// /*
1229    /// [dependencies]
1230    /// env_logger = "0.5.6"
1231    /// */
1232    /// #   Ok(())
1233    /// # }
1234    /// ```
1235    pub fn dependency<D: Into<Dependency>>(&mut self, dependency: D) -> &mut Self {
1236        if let Some(ref mut deps) = self.dependencies {
1237            deps.push(dependency.into());
1238        } else {
1239            self.dependencies = Some(vec![dependency.into()]);
1240        }
1241        self
1242    }
1243
1244    /// Set the `dependencies` table for the project
1245    ///
1246    /// **Note**: This will _replace_ any dependencies current attached to the object
1247    ///
1248    /// # Example
1249    ///
1250    /// ```rust
1251    /// extern crate cargo_toml_builder;
1252    ///
1253    /// use cargo_toml_builder::prelude::*;
1254    /// # use std::error::Error;
1255    /// # fn main() -> Result<(), Box<dyn Error>> {
1256    ///
1257    /// let cargo_toml = CargoToml::new()
1258    ///                     .dependencies(&[
1259    ///                         "env_logger".version("0.5.6"),
1260    ///                         "tokio".version("0.2"),
1261    ///                     ])
1262    /// #                   .author("me")
1263    /// #                   .name("my-project")
1264    ///                     .build()?;
1265    /// # let rendered = cargo_toml.to_string();
1266    /// # assert!(rendered.contains(r#"env_logger = "0.5.6""#));
1267    /// # assert!(rendered.contains(r#"tokio = "0.2""#));
1268    /// /*
1269    /// [dependencies]
1270    /// env_logger = "0.5.6"
1271    /// tokio = "0.2"
1272    /// */
1273    /// #   Ok(())
1274    /// # }
1275    /// ```
1276    pub fn dependencies<D: Into<Dependency> + Clone>(&mut self, dependencies: &[D]) -> &mut Self {
1277        self.dependencies = Some(dependencies.into_iter().cloned().map(|d| d.into()).collect());
1278        self
1279    }
1280
1281    /// Add a `dev-dependencies` entry to the project
1282    ///
1283    /// # Example
1284    ///
1285    /// ```rust
1286    /// extern crate cargo_toml_builder;
1287    ///
1288    /// use cargo_toml_builder::prelude::*;
1289    /// # use std::error::Error;
1290    /// # fn main() -> Result<(), Box<dyn Error>> {
1291    ///
1292    /// let cargo_toml = CargoToml::new()
1293    ///                     .dev_dependency("hamcrest".version("0.1.5"))
1294    /// #                   .author("me")
1295    /// #                   .name("my-project")
1296    ///                     .build()?;
1297    /// # let rendered = cargo_toml.to_string();
1298    /// # assert!(rendered.contains(r#"[dev-dependencies]"#));
1299    /// # assert!(rendered.contains(r#"hamcrest = "0.1.5""#));
1300    /// /*
1301    /// [dev-dependencies]
1302    /// hamcrest = "0.1.5"
1303    /// */
1304    /// #   Ok(())
1305    /// # }
1306    /// ```
1307    pub fn dev_dependency<D: Into<Dependency>>(&mut self, dependency: D) -> &mut Self {
1308        if let Some(ref mut deps) = self.dev_dependencies {
1309            deps.push(dependency.into());
1310        } else {
1311            self.dev_dependencies = Some(vec![dependency.into()]);
1312        }
1313        self
1314    }
1315
1316    /// Set the list of `dev-dependencies` for the project
1317    ///
1318    /// **Note**: This will _replace_ any dev-dependencies currently attached to the object
1319    ///
1320    /// # Example
1321    ///
1322    /// ```rust
1323    /// extern crate cargo_toml_builder;
1324    ///
1325    /// use cargo_toml_builder::prelude::*;
1326    /// # use std::error::Error;
1327    /// # fn main() -> Result<(), Box<dyn Error>> {
1328    ///
1329    /// let cargo_toml = CargoToml::new()
1330    ///                     .dev_dependencies(&[
1331    ///                         "hamcrest".version("0.1.5"),
1332    ///                         "my-test-lib".path("../my-test-lib")
1333    ///                     ])
1334    /// #                   .author("me")
1335    /// #                   .name("my-project")
1336    ///                     .build()?;
1337    /// # let rendered = cargo_toml.to_string();
1338    /// # assert!(rendered.contains(r#"[dev-dependencies]"#));
1339    /// # assert!(rendered.contains(r#"hamcrest = "0.1.5""#));
1340    /// # assert!(rendered.contains(r#"my-test-lib = {path = "../my-test-lib"}"#));
1341    /// /*
1342    /// [dev-dependencies]
1343    /// hamcrest = "0.1.5"
1344    /// my-test-lib = { path = "../my-test-lib" }
1345    /// */
1346    /// #   Ok(())
1347    /// # }
1348    /// ```
1349    pub fn dev_dependencies<D: Into<Dependency> + Clone>(&mut self, dependencies: &[D]) -> &mut Self {
1350        self.dev_dependencies = Some(dependencies.into_iter().cloned().map(|d| d.into()).collect());
1351        self
1352    }
1353
1354    /// Add an entry to the `build-dependencies` table for the project
1355    ///
1356    /// # Example
1357    ///
1358    /// ```rust
1359    /// extern crate cargo_toml_builder;
1360    ///
1361    /// use cargo_toml_builder::prelude::*;
1362    /// # use std::error::Error;
1363    /// # fn main() -> Result<(), Box<dyn Error>> {
1364    ///
1365    /// let cargo_toml = CargoToml::new()
1366    ///                     .build_dependency("gcc".version("0.3.54"))
1367    /// #                   .author("me")
1368    /// #                   .name("my-project")
1369    ///                     .build()?;
1370    /// # assert!(cargo_toml.to_string().contains(r#"[build-dependencies]"#));
1371    /// # assert!(cargo_toml.to_string().contains(r#"gcc = "0.3.54""#));
1372    /// /*
1373    /// [build-dependencies]
1374    /// gcc = "0.3.54"
1375    /// */
1376    /// #   Ok(())
1377    /// # }
1378    /// ```
1379    pub fn build_dependency<D: Into<Dependency>>(&mut self, dependency: D) -> &mut Self {
1380        if let Some(ref mut deps) = self.build_dependencies {
1381            deps.push(dependency.into());
1382        } else {
1383            self.build_dependencies = Some(vec![dependency.into()]);
1384        }
1385        self
1386    }
1387
1388    /// Set the list of `build-dependencies` for the project
1389    ///
1390    /// **Note**: this will _replace_ any build dependencies currently attached to the object
1391    ///
1392    /// # Example
1393    ///
1394    /// ```rust
1395    /// extern crate cargo_toml_builder;
1396    ///
1397    /// use cargo_toml_builder::prelude::*;
1398    /// # use std::error::Error;
1399    /// # fn main() -> Result<(), Box<dyn Error>> {
1400    ///
1401    /// let cargo_toml = CargoToml::new()
1402    ///                     .build_dependencies(&[
1403    ///                         "gcc".version("0.3.54"),
1404    ///                         "cmake".version("0.1.29"),
1405    ///                     ])
1406    /// #                   .author("me")
1407    /// #                   .name("my-project")
1408    ///                     .build()?;
1409    /// # let rendered = cargo_toml.to_string();
1410    /// # assert!(rendered.contains(r#"[build-dependencies]"#));
1411    /// # assert!(rendered.contains(r#"gcc = "0.3.54""#));
1412    /// # assert!(rendered.contains(r#"cmake = "0.1.29""#));
1413    /// /*
1414    /// [build-dependencies]
1415    /// gcc = "0.3.54"
1416    /// cmake = "0.1.29"
1417    /// */
1418    /// #   Ok(())
1419    /// # }
1420    /// ```
1421    pub fn build_dependencies<D: Into<Dependency> + Clone>(&mut self, dependencies: &[D]) -> &mut Self {
1422        self.build_dependencies = Some(dependencies.into_iter().cloned().map(|d| d.into()).collect());
1423        self
1424    }
1425
1426    /// Add a dependency to a target
1427    ///
1428    /// # Example
1429    ///
1430    /// ```rust
1431    /// extern crate cargo_toml_builder;
1432    ///
1433    /// use cargo_toml_builder::prelude::*;
1434    /// # use std::error::Error;
1435    /// # fn main() -> Result<(), Box<dyn Error>> {
1436    ///
1437    /// let cargo_toml = CargoToml::new()
1438    ///                     .target_dependency("cfg(unix)", "openssl".version("1.0.1"))
1439    /// #                   .author("me")
1440    /// #                   .name("my-project")
1441    ///                     .build()?;
1442    /// # let rendered = cargo_toml.to_string();
1443    /// # assert!(rendered.contains(r#"[target."cfg(unix)".dependencies]"#));
1444    /// # assert!(rendered.contains(r#"openssl = "1.0.1""#));
1445    /// /*
1446    /// [target."cfg(unix)".dependencies]
1447    /// openssl = "1.0.1"
1448    /// */
1449    /// #   Ok(())
1450    /// # }
1451    /// ```
1452    pub fn target_dependency<D: Into<Dependency>>(&mut self, name: &str, dependency: D) -> &mut Self {
1453        if let Some(ref mut map) = self.target_dependencies {
1454            let deps = map.entry(name.into()).or_insert(vec![]);
1455            deps.push(dependency.into());
1456        } else {
1457            let mut map = HashMap::new();
1458            map.insert(name.into(), vec![dependency.into()]);
1459            self.target_dependencies = Some(map);
1460        }
1461        self
1462    }
1463
1464    /// Set the dependency list for a target
1465    ///
1466    /// **Note**: This will _replace_ any dependencies current attached to the target
1467    ///
1468    /// # Example
1469    ///
1470    /// ```rust
1471    /// extern crate cargo_toml_builder;
1472    ///
1473    /// use cargo_toml_builder::prelude::*;
1474    /// # use std::error::Error;
1475    /// # fn main() -> Result<(), Box<dyn Error>> {
1476    ///
1477    /// let cargo_toml = CargoToml::new()
1478    ///                     .target_dependencies("cfg(unix)", &[
1479    ///                         "openssl".version("1.0.1"),
1480    ///                         "libc".version("0.2.40"),
1481    ///                     ])
1482    /// #                   .author("me")
1483    /// #                   .name("my-project")
1484    ///                     .build()?;
1485    /// # let rendered = cargo_toml.to_string();
1486    /// # assert!(rendered.contains(r#"[target."cfg(unix)".dependencies]"#));
1487    /// # assert!(rendered.contains(r#"openssl = "1.0.1""#));
1488    /// # assert!(rendered.contains(r#"libc = "0.2.40""#));
1489    /// /*
1490    /// [target."cfg(unix)".dependencies]
1491    /// openssl = "1.0.1"
1492    /// libc = "0.2.40"
1493    /// */
1494    /// #   Ok(())
1495    /// # }
1496    /// ```
1497    pub fn target_dependencies<D: Into<Dependency> + Clone>(&mut self, name: &str, dependencies: &[D]) -> &mut Self {
1498        let deps = dependencies.into_iter().cloned().map(|d| d.into()).collect();
1499        if let Some(ref mut map) = self.target_dependencies {
1500            map.insert(name.into(), deps);
1501        } else {
1502            let mut map = HashMap::new();
1503            map.insert(name.into(), deps);
1504            self.target_dependencies = Some(map);
1505        }
1506        self
1507    }
1508
1509    /// Set the properties of the dev profile
1510    ///
1511    /// # Example
1512    ///
1513    /// ```rust
1514    /// extern crate cargo_toml_builder;
1515    ///
1516    /// use cargo_toml_builder::prelude::*;
1517    /// use cargo_toml_builder::types::{Profile, PanicStrategy};
1518    /// # use std::error::Error;
1519    /// # fn main() -> Result<(), Box<dyn Error>> {
1520    ///
1521    /// let profile = Profile::new().panic(PanicStrategy::Abort).build();
1522    /// let cargo_toml = CargoToml::new()
1523    ///                     .profile_dev(profile)
1524    /// #                   .author("me")
1525    /// #                   .name("my-project")
1526    ///                     .build()?;
1527    /// # assert!(cargo_toml.to_string().contains(r#"[profile.dev]"#));
1528    /// # assert!(cargo_toml.to_string().contains(r#"panic = "abort""#));
1529    /// /*
1530    /// [profile.dev]
1531    /// panic = "abort"
1532    /// */
1533    /// #   Ok(())
1534    /// # }
1535    /// ```
1536    pub fn profile_dev(&mut self, profile_dev: Profile) -> &mut Self {
1537        self.profile_dev = Some(profile_dev);
1538        self
1539    }
1540
1541    /// Set the properties of the release profile
1542    ///
1543    /// # Example
1544    ///
1545    /// ```rust
1546    /// extern crate cargo_toml_builder;
1547    ///
1548    /// use cargo_toml_builder::prelude::*;
1549    /// use cargo_toml_builder::types::{Profile, PanicStrategy};
1550    /// # use std::error::Error;
1551    /// # fn main() -> Result<(), Box<dyn Error>> {
1552    ///
1553    /// let profile = Profile::new().panic(PanicStrategy::Abort).build();
1554    /// let cargo_toml = CargoToml::new()
1555    ///                     .profile_release(profile)
1556    /// #                   .author("me")
1557    /// #                   .name("my-project")
1558    ///                     .build()?;
1559    /// # let rendered = cargo_toml.to_string();
1560    /// # assert!(rendered.contains(r#"[profile.release]"#));
1561    /// # assert!(rendered.contains(r#"panic = "abort""#));
1562    /// /*
1563    /// [profile.release]
1564    /// panic = "abort"
1565    /// */
1566    /// #   Ok(())
1567    /// # }
1568    /// ```
1569    pub fn profile_release(&mut self, profile_dev: Profile) -> &mut Self {
1570        self.profile_release = Some(profile_dev);
1571        self
1572    }
1573
1574    /// Set the properties of the test profile
1575    ///
1576    /// # Example
1577    ///
1578    /// ```rust
1579    /// extern crate cargo_toml_builder;
1580    ///
1581    /// use cargo_toml_builder::prelude::*;
1582    /// use cargo_toml_builder::types::{Profile, PanicStrategy};
1583    /// # use std::error::Error;
1584    /// # fn main() -> Result<(), Box<dyn Error>> {
1585    ///
1586    /// let profile = Profile::new().panic(PanicStrategy::Abort).build();
1587    /// let cargo_toml = CargoToml::new()
1588    ///                     .profile_test(profile)
1589    /// #                   .author("me")
1590    /// #                   .name("my-project")
1591    ///                     .build()?;
1592    /// # let rendered = cargo_toml.to_string();
1593    /// # assert!(rendered.contains(r#"[profile.test]"#));
1594    /// # assert!(rendered.contains(r#"panic = "abort""#));
1595    /// /*
1596    /// [profile.test]
1597    /// panic = "abort"
1598    /// */
1599    /// #   Ok(())
1600    /// # }
1601    /// ```
1602    pub fn profile_test(&mut self, profile_dev: Profile) -> &mut Self {
1603        self.profile_test = Some(profile_dev);
1604        self
1605    }
1606
1607    /// Set the properties of the bench profile
1608    ///
1609    /// # Example
1610    ///
1611    /// ```rust
1612    /// extern crate cargo_toml_builder;
1613    ///
1614    /// use cargo_toml_builder::prelude::*;
1615    /// use cargo_toml_builder::types::{Profile, PanicStrategy};
1616    /// # use std::error::Error;
1617    /// # fn main() -> Result<(), Box<dyn Error>> {
1618    ///
1619    /// let profile = Profile::new().panic(PanicStrategy::Abort).build();
1620    /// let cargo_toml = CargoToml::new()
1621    ///                     .profile_bench(profile)
1622    /// #                   .author("me")
1623    /// #                   .name("my-project")
1624    ///                     .build()?;
1625    /// # let rendered = cargo_toml.to_string();
1626    /// # assert!(rendered.contains("[profile.bench]"));
1627    /// # assert!(rendered.contains(r#"panic = "abort""#));
1628    /// /*
1629    /// [profile.bench]
1630    /// panic = "abort"
1631    /// */
1632    /// #   Ok(())
1633    /// # }
1634    /// ```
1635    pub fn profile_bench(&mut self, profile_dev: Profile) -> &mut Self {
1636        self.profile_bench = Some(profile_dev);
1637        self
1638    }
1639
1640    /// Set the properties of the doc profile
1641    ///
1642    /// # Example
1643    ///
1644    /// ```rust
1645    /// extern crate cargo_toml_builder;
1646    ///
1647    /// use cargo_toml_builder::prelude::*;
1648    /// use cargo_toml_builder::types::{Profile, PanicStrategy};
1649    /// # use std::error::Error;
1650    /// # fn main() -> Result<(), Box<dyn Error>> {
1651    ///
1652    /// let profile = Profile::new().panic(PanicStrategy::Abort).build();
1653    /// let cargo_toml = CargoToml::new()
1654    ///                     .profile_doc(profile)
1655    /// #                   .author("me")
1656    /// #                   .name("my-project")
1657    ///                     .build()?;
1658    /// # let rendered = cargo_toml.to_string();
1659    /// # assert!(rendered.contains("[profile.doc]"));
1660    /// # assert!(rendered.contains(r#"panic = "abort""#));
1661    /// /*
1662    /// [profile.doc]
1663    /// panic = "abort"
1664    /// */
1665    /// #   Ok(())
1666    /// # }
1667    /// ```
1668    pub fn profile_doc(&mut self, profile_dev: Profile) -> &mut Self {
1669        self.profile_doc = Some(profile_dev);
1670        self
1671    }
1672
1673    /// Add a feature to the project
1674    ///
1675    /// The user can attach dependencies, and the labels for other features, to a `Feature` object.
1676    /// If a Dependency is added, it will automatically be added to the `[dependencies]` section of
1677    /// the document with the `optional = true` option added. If you need different behavior, add
1678    /// the name of the dependency using the `.feature` builder method and add the dependency to
1679    /// the correct section manually.
1680    ///
1681    /// # Example
1682    ///
1683    /// ```rust
1684    /// extern crate cargo_toml_builder;
1685    ///
1686    /// use cargo_toml_builder::prelude::*;
1687    /// # use std::error::Error;
1688    /// # fn main() -> Result<(), Box<dyn Error>> {
1689    ///
1690    /// let nightly = Feature::new("nightly").dependency("clippy".version("0.0.191")).build();
1691    /// let cargo_toml = CargoToml::new()
1692    ///                     .feature(nightly)
1693    /// #                   .author("me")
1694    /// #                   .name("my-project")
1695    ///                     .build()?;
1696    /// # let rendered = cargo_toml.to_string();
1697    /// # assert!(rendered.contains(r#"[features]"#));
1698    /// # assert!(rendered.contains(r#"nightly = ["clippy"]"#));
1699    /// # assert!(rendered.contains(r#"clippy = {version = "0.0.191",optional = true}"#));
1700    /// /*
1701    /// [features]
1702    /// nightly = ['clippy']
1703    ///
1704    /// [dependencies]
1705    /// clippy = { version = "0.0.191", optional = true }
1706    /// */
1707    /// #   Ok(())
1708    /// # }
1709    /// ```
1710    ///
1711    /// Or, to add a feature dependency to, say, `[dev-dependencies]`:
1712    ///
1713    /// ```rust
1714    /// extern crate cargo_toml_builder;
1715    ///
1716    /// use cargo_toml_builder::prelude::*;
1717    /// # use std::error::Error;
1718    /// # fn main() -> Result<(), Box<dyn Error>> {
1719    ///
1720    /// let nightly = Feature::new("nightly").feature("clippy").build();
1721    /// let cargo_toml = CargoToml::new()
1722    ///                     .feature(nightly)
1723    ///                     .dev_dependency("clippy".version("0.0.191").optional(true))
1724    /// #                   .author("me")
1725    /// #                   .name("my-project")
1726    ///                     .build()?;
1727    /// # let rendered = cargo_toml.to_string();
1728    /// # assert!(rendered.contains(r#"[features]"#));
1729    /// # assert!(rendered.contains(r#"nightly = ["clippy"]"#));
1730    /// # assert!(rendered.contains(r#"[dev-dependencies]"#));
1731    /// # assert!(rendered.contains(r#"clippy = {version = "0.0.191",optional = true}"#));
1732    /// /*
1733    /// [features]
1734    /// nightly = ['clippy']
1735    ///
1736    /// [dev-dependencies]
1737    /// clippy = { version = "0.0.191", optional = true }
1738    /// */
1739    /// #   Ok(())
1740    /// # }
1741    /// ```
1742    pub fn feature<F: Into<Feature>>(&mut self, feature: F) -> &mut Self {
1743        if let Some(ref mut v) = self.features {
1744            v.push(feature.into());
1745        } else {
1746            self.features = Some(vec![feature.into()]);
1747        }
1748        self
1749    }
1750
1751    /// Set the workspace config table for the project
1752    ///
1753    /// # Example
1754    ///
1755    /// ```rust
1756    /// extern crate cargo_toml_builder;
1757    ///
1758    /// use cargo_toml_builder::prelude::*;
1759    /// use cargo_toml_builder::types::Workspace;
1760    /// # use std::error::Error;
1761    /// # fn main() -> Result<(), Box<dyn Error>> {
1762    ///
1763    /// let workspace = Workspace::new().member("/path/to/member1").build();
1764    /// let cargo_toml = CargoToml::new()
1765    ///                     .workspace(workspace)
1766    /// #                   .author("me")
1767    /// #                   .name("my-project")
1768    ///                     .build()?;
1769    /// # let rendered = cargo_toml.to_string();
1770    /// # assert!(rendered.contains("[workspace]"));
1771    /// # assert!(rendered.contains(r#"members = ["/path/to/member1"]"#));
1772    /// /*
1773    /// [workspace]
1774    /// members = ["/path/to/member1"]
1775    /// */
1776    /// #   Ok(())
1777    /// # }
1778    /// ```
1779    pub fn workspace(&mut self, workspace: Workspace) -> &mut Self {
1780        self.workspace = Some(workspace);
1781        self
1782    }
1783
1784    /// Set a `[lib]` target for the project
1785    ///
1786    /// # Example
1787    ///
1788    /// ```rust
1789    /// extern crate cargo_toml_builder;
1790    ///
1791    /// use cargo_toml_builder::prelude::*;
1792    ///
1793    /// # use std::error::Error;
1794    /// # fn main() -> Result<(), Box<dyn Error>> {
1795    /// let target = LibTarget::new().name("my-lib").path("src/my-lib.rs").build();
1796    /// let cargo_toml = CargoToml::new()
1797    ///                     .lib(target)
1798    /// #                   .author("me")
1799    /// #                   .name("my-project")
1800    ///                     .build()?;
1801    /// # let rendered = cargo_toml.to_string();
1802    /// # assert!(rendered.contains("[lib]"));
1803    /// # assert!(rendered.contains(r#"name = "my-lib""#));
1804    /// # assert!(rendered.contains(r#"path = "src/my-lib.rs""#));
1805    /// /*
1806    /// [lib]
1807    /// name = "my-lib"
1808    /// path = "src/my-lib.rs"
1809    /// */
1810    /// #   Ok(())
1811    /// # }
1812    /// ```
1813    pub fn lib<T: Into<LibTarget>>(&mut self, target: T) -> &mut Self {
1814        self.lib = Some(target.into());
1815        self
1816    }
1817
1818    /// Add a `[[bin]]` target for the project
1819    ///
1820    /// # Example
1821    ///
1822    /// ```rust
1823    /// extern crate cargo_toml_builder;
1824    ///
1825    /// use cargo_toml_builder::prelude::*;
1826    /// # use std::error::Error;
1827    /// # fn main() -> Result<(), Box<dyn Error>> {
1828    ///
1829    /// let target = BinTarget::new().name("my-bin").path("src/bin/my-bin.rs").build();
1830    /// let cargo_toml = CargoToml::new()
1831    ///                     .bin(target)
1832    /// #                   .author("me")
1833    /// #                   .name("my-project")
1834    ///                     .build()?;
1835    /// # let rendered = cargo_toml.to_string();
1836    /// # assert!(rendered.contains("[[bin]]"));
1837    /// # assert!(rendered.contains(r#"name = "my-bin""#));
1838    /// # assert!(rendered.contains(r#"path = "src/bin/my-bin.rs""#));
1839    /// /*
1840    /// [dependencies]
1841    /// <name> = <value>
1842    /// */
1843    /// #   Ok(())
1844    /// # }
1845    /// ```
1846    pub fn bin<T: Into<BinTarget>>(&mut self, target: T) -> &mut Self {
1847        if let Some(ref mut v) = self.bins {
1848            v.push(target.into());
1849        } else {
1850            self.bins = Some(vec![target.into()]);
1851        }
1852        self
1853    }
1854
1855    /// Set the `[[bin]]` targets for the project
1856    ///
1857    /// **Note**: This will _replace_ any bin targets currently attached to the project
1858    ///
1859    /// # Example
1860    ///
1861    /// ```rust
1862    /// extern crate cargo_toml_builder;
1863    ///
1864    /// use cargo_toml_builder::prelude::*;
1865    /// # use std::error::Error;
1866    /// # fn main() -> Result<(), Box<dyn Error>> {
1867    /// let cargo_toml = CargoToml::new()
1868    ///                     .bins(&[
1869    ///                         BinTarget::new().name("my-bin-1").path("src/bin/my-bin-1.rs").build(),
1870    ///                         BinTarget::new().name("my-bin-2").path("src/bin/my-bin-2.rs").build(),
1871    ///                     ])
1872    /// #                   .author("me")
1873    /// #                   .name("my-project")
1874    ///                     .build()?;
1875    /// # let rendered = cargo_toml.to_string();
1876    /// # assert!(rendered.contains("[[bin]]"));
1877    /// # assert!(rendered.contains(r#"name = "my-bin-1""#));
1878    /// # assert!(rendered.contains(r#"name = "my-bin-2""#));
1879    /// # assert!(rendered.contains(r#"path = "src/bin/my-bin-1.rs""#));
1880    /// # assert!(rendered.contains(r#"path = "src/bin/my-bin-2.rs""#));
1881    /// /*
1882    /// [dependencies]
1883    /// <name> = <value>
1884    /// */
1885    /// #   Ok(())
1886    /// # }
1887    /// ```
1888    pub fn bins(&mut self, target: &[BinTarget]) -> &mut Self {
1889        self.bins = Some(target.to_vec());
1890        self
1891    }
1892
1893    /// Add a `[bench]` target for the project
1894    ///
1895    /// # Example
1896    ///
1897    /// ```rust
1898    /// extern crate cargo_toml_builder;
1899    ///
1900    /// use cargo_toml_builder::prelude::*;
1901    /// # use std::error::Error;
1902    /// # fn main() -> Result<(), Box<dyn Error>> {
1903    ///
1904    /// let target = BenchTarget::new().name("my-benchmark").path("bench/my-benchmark.rs").build();
1905    /// let cargo_toml = CargoToml::new()
1906    ///                     .bench(target)
1907    /// #                   .author("me")
1908    /// #                   .name("my-project")
1909    ///                     .build()?;
1910    /// # let rendered = cargo_toml.to_string();
1911    /// # assert!(rendered.contains("[[bench]]"));
1912    /// # assert!(rendered.contains(r#"name = "my-benchmark""#));
1913    /// # assert!(rendered.contains(r#"path = "bench/my-benchmark.rs""#));
1914    /// /*
1915    /// [dependencies]
1916    /// <name> = <value>
1917    /// */
1918    /// #   Ok(())
1919    /// # }
1920    /// ```
1921    pub fn bench<T: Into<BenchTarget>>(&mut self, target: T) -> &mut Self {
1922        if let Some(ref mut v) = self.benches {
1923            v.push(target.into());
1924        } else {
1925            self.benches = Some(vec![target.into()]);
1926        }
1927        self
1928    }
1929
1930    /// Set the list of `[[bench]]` targets for the project
1931    ///
1932    /// **Note**: This will _replace_ any bench targets currently attached to the project
1933    ///
1934    /// # Example
1935    ///
1936    /// ```rust
1937    /// extern crate cargo_toml_builder;
1938    ///
1939    /// use cargo_toml_builder::prelude::*;
1940    /// # use std::error::Error;
1941    /// # fn main() -> Result<(), Box<dyn Error>> {
1942    ///
1943    /// let cargo_toml = CargoToml::new()
1944    ///                     .benches(&[
1945    ///                         BenchTarget::new().name("my-benchmark-1").path("bench/my-benchmark-1.rs").build(),
1946    ///                         BenchTarget::new().name("my-benchmark-2").path("bench/my-benchmark-2.rs").build(),
1947    ///                     ])
1948    /// #                   .author("me")
1949    /// #                   .name("my-project")
1950    ///                     .build()?;
1951    ///
1952    /// # let rendered = cargo_toml.to_string();
1953    /// # assert!(rendered.contains("[[bench]]"));
1954    /// # assert!(rendered.contains(r#"name = "my-benchmark-1""#));
1955    /// # assert!(rendered.contains(r#"name = "my-benchmark-2""#));
1956    /// # assert!(rendered.contains(r#"path = "bench/my-benchmark-1.rs""#));
1957    /// # assert!(rendered.contains(r#"path = "bench/my-benchmark-2.rs""#));
1958    /// /*
1959    /// [[bench]]
1960    /// name = "my-benchmark-1"
1961    /// path = "bench/my-benchmark-1.rs"
1962    ///
1963    /// [[bench]]
1964    /// name = "my-benchmark-2"
1965    /// path = "bench/my-benchmark-2.rs"
1966    /// */
1967    /// #   Ok(())
1968    /// # }
1969    /// ```
1970    pub fn benches(&mut self, target: &[BenchTarget]) -> &mut Self {
1971        self.benches = Some(target.to_vec());
1972        self
1973    }
1974
1975    /// Add a `[[test]]` target to the project
1976    ///
1977    /// # Example
1978    ///
1979    /// ```rust
1980    /// extern crate cargo_toml_builder;
1981    ///
1982    /// use cargo_toml_builder::prelude::*;
1983    /// # use std::error::Error;
1984    /// # fn main() -> Result<(), Box<dyn Error>> {
1985    ///
1986    /// let target = TestTarget::new().name("my-test").path("tests/my-test.rs").build();
1987    /// let cargo_toml = CargoToml::new()
1988    ///                     .test(target)
1989    /// #                   .author("me")
1990    /// #                   .name("my-project")
1991    ///                     .build()?;
1992    /// # let rendered = cargo_toml.to_string();
1993    /// # assert!(rendered.contains("[[test]]"));
1994    /// # assert!(rendered.contains(r#"name = "my-test""#));
1995    /// # assert!(rendered.contains(r#"path = "tests/my-test.rs""#));
1996    /// /*
1997    /// [[test]]
1998    /// name = "my-test"
1999    /// path = "tests/my-test.rs"
2000    /// */
2001    /// #   Ok(())
2002    /// # }
2003    /// ```
2004    pub fn test<T: Into<TestTarget>>(&mut self, target: T) -> &mut Self {
2005        if let Some(ref mut v) = self.tests {
2006            v.push(target.into());
2007        } else {
2008            self.tests = Some(vec![target.into()]);
2009        }
2010        self
2011    }
2012
2013    /// Set the `[[test]]` targets for the project
2014    ///
2015    /// **Note**: This will _replace_ any test targets currently attached to the project
2016    ///
2017    /// # Example
2018    ///
2019    /// ```rust
2020    /// extern crate cargo_toml_builder;
2021    ///
2022    /// use cargo_toml_builder::prelude::*;
2023    /// # use std::error::Error;
2024    /// # fn main() -> Result<(), Box<dyn Error>> {
2025    ///
2026    /// let cargo_toml = CargoToml::new()
2027    ///                     .tests(&[
2028    ///                         TestTarget::new().name("my-test-1").path("tests/my-test-1.rs").build(),
2029    ///                         TestTarget::new().name("my-test-2").path("tests/my-test-2.rs").build(),
2030    ///                     ])
2031    /// #                   .author("me")
2032    /// #                   .name("my-project")
2033    ///                     .build()?;
2034    /// # let rendered = cargo_toml.to_string();
2035    /// # assert!(rendered.contains("[[test]]"));
2036    /// # assert!(rendered.contains(r#"name = "my-test-1""#));
2037    /// # assert!(rendered.contains(r#"name = "my-test-2""#));
2038    /// # assert!(rendered.contains(r#"path = "tests/my-test-1.rs""#));
2039    /// # assert!(rendered.contains(r#"path = "tests/my-test-2.rs""#));
2040    /// /*
2041    /// [[test]]
2042    /// name = "my-test-1"
2043    /// path = "tests/my-test-1.rs"
2044    ///
2045    /// [[test]]
2046    /// name = "my-test-2"
2047    /// path = "tests/my-test-2.rs"
2048    /// */
2049    /// #   Ok(())
2050    /// # }
2051    /// ```
2052    pub fn tests(&mut self, target: &[TestTarget]) -> &mut Self {
2053        self.tests = Some(target.to_vec());
2054        self
2055    }
2056
2057    /// Add an `[[example]]` target to the project
2058    ///
2059    /// # Example
2060    ///
2061    /// ```rust
2062    /// extern crate cargo_toml_builder;
2063    ///
2064    /// use cargo_toml_builder::prelude::*;
2065    /// # use std::error::Error;
2066    /// # fn main() -> Result<(), Box<dyn Error>> {
2067    ///
2068    /// let target = ExampleTarget::new().name("my-example").path("examples/my-example.rs").build();
2069    /// let cargo_toml = CargoToml::new()
2070    ///                     .example(target)
2071    /// #                   .author("me")
2072    /// #                   .name("my-project")
2073    ///                     .build()?;
2074    /// # let rendered = cargo_toml.to_string();
2075    /// # assert!(rendered.contains("[[example]]"));
2076    /// # assert!(rendered.contains(r#"name = "my-example""#));
2077    /// # assert!(rendered.contains(r#"path = "examples/my-example.rs""#));
2078    /// /*
2079    /// [[example]]
2080    /// name = "my-example"
2081    /// path = "examples/my-example.rs"
2082    /// */
2083    /// #   Ok(())
2084    /// # }
2085    /// ```
2086    pub fn example<T: Into<ExampleTarget>>(&mut self, target: T) -> &mut Self {
2087        if let Some(ref mut v) = self.examples {
2088            v.push(target.into());
2089        } else {
2090            self.examples = Some(vec![target.into()]);
2091        }
2092        self
2093    }
2094
2095    /// Set the list of `[[example]]` targets for the project
2096    //
2097    /// **Note**: This will _replace_ any `[[example]]` targets currently attached to the project
2098    ///
2099    /// # Example
2100    ///
2101    /// ```rust
2102    /// extern crate cargo_toml_builder;
2103    ///
2104    /// use cargo_toml_builder::prelude::*;
2105    /// # use std::error::Error;
2106    /// # fn main() -> Result<(), Box<dyn Error>> {
2107    ///
2108    /// let cargo_toml = CargoToml::new()
2109    ///                     .examples(&[
2110    ///                         ExampleTarget::new().name("my-example-1").path("examples/my-example-1.rs").build(),
2111    ///                         ExampleTarget::new().name("my-example-2").path("examples/my-example-2.rs").build(),
2112    ///                     ])
2113    /// #                   .author("me")
2114    /// #                   .name("my-project")
2115    ///                     .build()?;
2116    /// # let rendered = cargo_toml.to_string();
2117    /// # assert!(rendered.contains("[[example]]"));
2118    /// # assert!(rendered.contains(r#"name = "my-example-1""#));
2119    /// # assert!(rendered.contains(r#"name = "my-example-2""#));
2120    /// # assert!(rendered.contains(r#"path = "examples/my-example-1.rs""#));
2121    /// # assert!(rendered.contains(r#"path = "examples/my-example-2.rs""#));
2122    /// /*
2123    /// [[example]]
2124    /// name = "my-example-1"
2125    /// path = "examples/my-example-1.rs"
2126    ///
2127    /// [[example]]
2128    /// name = "my-example-2"
2129    /// path = "examples/my-example-2.rs"
2130    /// */
2131    /// #   Ok(())
2132    /// # }
2133    /// ```
2134    pub fn examples(&mut self, target: &[ExampleTarget]) -> &mut Self {
2135        self.examples = Some(target.to_vec());
2136        self
2137    }
2138
2139    /// <DESCRIPTION>
2140    ///
2141    /// # Example
2142    ///
2143    /// ```rust
2144    /// extern crate cargo_toml_builder;
2145    ///
2146    /// use cargo_toml_builder::prelude::*;
2147    /// use cargo_toml_builder::types::PatchSet;
2148    /// # use std::error::Error;
2149    /// # fn main() -> Result<(), Box<dyn Error>> {
2150    /// let patchset = PatchSet::new("crates-io")
2151    ///                         .patch("env_logger".repo("https://gitlab.com/me/env_logger.git"))
2152    ///                         .build();
2153    /// let cargo_toml = CargoToml::new()
2154    ///                     .patch(patchset)
2155    /// #                   .author("me")
2156    /// #                   .name("my-project")
2157    ///                     .build()?;
2158    /// # let rendered = cargo_toml.to_string();
2159    /// # assert!(rendered.contains("[patch.crates-io]"));
2160    /// # assert!(rendered.contains(r#"env_logger = {git = "https://gitlab.com/me/env_logger.git"}"#));
2161    /// /*
2162    /// [patch.crates-io]
2163    /// env_logger = { git = "https://gitlab.com/me/env_logger.git" }
2164    /// */
2165    /// #   Ok(())
2166    /// # }
2167    /// ```
2168    pub fn patch(&mut self, patch: PatchSet) -> &mut Self {
2169        if let Some(ref mut v) = self.patches {
2170            v.push(patch);
2171        } else {
2172            self.patches = Some(vec![patch]);
2173        }
2174        self
2175    }
2176
2177    /// Set the list of patch sets for the project
2178    ///
2179    /// **Note**: This will _replace_ any patch sets currently attached to the object
2180    ///
2181    /// # Example
2182    ///
2183    /// ```rust
2184    /// extern crate cargo_toml_builder;
2185    ///
2186    /// use cargo_toml_builder::prelude::*;
2187    /// use cargo_toml_builder::types::PatchSet;
2188    /// # use std::error::Error;
2189    /// # fn main() -> Result<(), Box<dyn Error>> {
2190    /// let cargo_toml = CargoToml::new()
2191    ///                     .patches(&[
2192    ///                         PatchSet::new("crates-io")
2193    ///                                  .patch("env_logger".repo("https://gitlab.com/me/env_logger.git"))
2194    ///                                  .build(),
2195    ///                         PatchSet::new("https://github.com/example/baz")
2196    ///                                  .patch("baz".repo("https://github.com/example/patched-baz"))
2197    ///                                  .build(),
2198    ///                     ])
2199    /// #                   .author("me")
2200    /// #                   .name("my-project")
2201    ///                     .build()?;
2202    /// # let rendered = cargo_toml.to_string();
2203    /// # assert!(rendered.contains("[patch.crates-io]"));
2204    /// # assert!(rendered.contains(r#"[patch."https://github.com/example/baz"]"#));
2205    /// # assert!(rendered.contains(r#"env_logger = {git = "https://gitlab.com/me/env_logger.git"}"#));
2206    /// # assert!(rendered.contains(r#"baz = {git = "https://github.com/example/patched-baz"}"#));
2207    /// /*
2208    /// [patch.crates-io]
2209    /// env_logger = { git = "https://gitlab.com/me/env_logger.git" }
2210    ///
2211    /// [patch."https://github.com/example/baz"]
2212    /// baz = { git = "https://github.com/example/patched-baz" }
2213    /// */
2214    /// #   Ok(())
2215    /// # }
2216    /// ```
2217    pub fn patches(&mut self, patches: &[PatchSet]) -> &mut Self {
2218        self.patches = Some(patches.to_vec());
2219        self
2220    }
2221
2222    /// Add a `[replace]` entry to the project
2223    ///
2224    /// # Example
2225    ///
2226    /// ```rust
2227    /// extern crate cargo_toml_builder;
2228    ///
2229    /// use cargo_toml_builder::prelude::*;
2230    /// # use std::error::Error;
2231    /// # fn main() -> Result<(), Box<dyn Error>> {
2232    /// let cargo_toml = CargoToml::new()
2233    ///                     .replace("foo:0.1.0".repo("https://github.com/example/foo"))
2234    /// #                   .author("me")
2235    /// #                   .name("my-project")
2236    ///                     .build()?;
2237    /// # let rendered = cargo_toml.to_string();
2238    /// # assert!(rendered.contains("[replace]"));
2239    /// # assert!(rendered.contains(r#""foo:0.1.0" = {git = "https://github.com/example/foo"}"#));
2240    /// /*
2241    /// [replace]
2242    /// "foo:0.1.0" = { git = "https://github.com/example/foo" }
2243    /// */
2244    /// #   Ok(())
2245    /// # }
2246    /// ```
2247    pub fn replace<D: Into<Dependency>>(&mut self, dependency: D) -> &mut Self {
2248        let replace = Replace::new(dependency.into());
2249        if let Some(ref mut v) = self.replacements {
2250            v.push(replace);
2251        } else {
2252            self.replacements = Some(vec![replace]);
2253        }
2254        self
2255    }
2256
2257    /// Build a `toml_edit::Document` object from this builder
2258    ///
2259    /// # Example
2260    ///
2261    /// ```rust
2262    /// extern crate cargo_toml_builder;
2263    /// use cargo_toml_builder::prelude::*;
2264    /// # use std::error::Error;
2265    /// # fn main() -> Result<(), Box<dyn Error>> {
2266    ///
2267    /// let cargo_toml = CargoToml::new()
2268    ///                     .name("my-project")
2269    ///                     .author("Me <me@me.com>")
2270    ///                     .build()?;
2271    /// /*
2272    /// [package]
2273    /// name = "my-project"
2274    /// version = "0.1.0"
2275    /// authors = ["Me <me@me.com>"]
2276    ///
2277    /// [dependencies]
2278    /// */
2279    /// #   Ok(())
2280    /// # }
2281    /// ```
2282    pub fn build(&self) -> Result<Document, Error> {
2283        Ok(TomlOutput::new(self).document()?)
2284    }
2285}
2286