Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: improve the public interface by using triats #3

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 84 additions & 70 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::ffi::{CString, NulError};
use std::os::raw::c_uchar;

use crate::go::guess::GoGuess;
use crate::go::slice::{GoSlice, ToGoSlice};
use crate::go::string::{GoString, ToGoString};
use crate::go::guess::GoGuess;

pub use go::guess::Guess;

Expand Down Expand Up @@ -54,12 +54,19 @@ extern "C" {
/// detection will be based on the filename. The function won't read the file, given an empty content.
///
/// [Linguist.detect]: https://github.com/github/linguist/blob/aad49acc0624c70d654a8dce447887dbbc713c7a/lib/linguist.rb#L14-L49
pub fn get_languages(filename: &str, content: &[u8]) -> Result<Vec<String>, NulError> {
let c_filename = CString::new(filename).expect("Can't construct string");
let c_content = CString::new(content).expect("Can't construct content string");
pub fn get_languages<S: AsRef<str>, B: AsRef<[u8]>>(
filename: S,
content: B,
) -> Result<Vec<String>, NulError> {
let c_filename = CString::new(filename.as_ref()).expect("Can't construct string");
let c_content = CString::new(content.as_ref()).expect("Can't construct content string");
let mut go_result = GoSlice::default();
unsafe {
GetLanguages(c_filename.as_go_string(), c_content.as_go_slice(), &mut go_result);
GetLanguages(
c_filename.as_go_string(),
c_content.as_go_slice(),
&mut go_result,
);
Ok(Vec::from(go_result))
}
}
Expand All @@ -70,24 +77,23 @@ pub fn get_languages(filename: &str, content: &[u8]) -> Result<Vec<String>, NulE
///
/// If there are more than one possibles languages it returns the first language
/// by alphabetically order and the `safe` field of `Guess` will be set to false.
pub fn get_language_by_content(filename: &str, content: &[u8]) -> Result<Guess, NulError> {
let c_filename = CString::new(filename)?;
let c_content = CString::new(content)?;
pub fn get_language_by_content<S: AsRef<str>, B: AsRef<[u8]>>(
filename: S,
content: B,
) -> Result<Guess, NulError> {
let c_filename = CString::new(filename.as_ref())?;
let c_content = CString::new(content.as_ref())?;
unsafe {
Ok(
Guess::from(
GetLanguageByContent(
c_filename.as_go_string(),
c_content.as_go_slice(),
)
)
)
Ok(Guess::from(GetLanguageByContent(
c_filename.as_go_string(),
c_content.as_go_slice(),
)))
}
}

/// `get_language_extensions()` returns all extensions associated with the given language.
pub fn get_language_extensions(language: &str) -> Result<Vec<String>, NulError> {
let c_language = CString::new(language)?;
pub fn get_language_extensions<S: AsRef<str>>(language: S) -> Result<Vec<String>, NulError> {
let c_language = CString::new(language.as_ref())?;
let mut go_result = GoSlice::default();
unsafe {
GetLanguageExtensions(c_language.as_go_string(), &mut go_result);
Expand All @@ -97,131 +103,139 @@ pub fn get_language_extensions(language: &str) -> Result<Vec<String>, NulError>

/// `get_language()` applies a sequence of strategies based on the given filename
/// and content to find out the most probable language to return.
pub fn get_language(filename: &str, content: &[u8]) -> Result<String, NulError> {
let c_filename = CString::new(filename)?;
let c_content = CString::new(content)?;
unsafe {
Ok(
GetLanguage(
c_filename.as_go_string(),
c_content.as_go_slice(),
)
.to_string()
)
}
pub fn get_language<S: AsRef<str>, B: AsRef<[u8]>>(
filename: S,
content: B,
) -> Result<String, NulError> {
let c_filename = CString::new(filename.as_ref())?;
let c_content = CString::new(content.as_ref())?;
unsafe { Ok(GetLanguage(c_filename.as_go_string(), c_content.as_go_slice()).to_string()) }
}

/// `get_mime_type()` returns a MIME type of a given file based on its languages.
pub fn get_mime_type(path: &str, language: &str) -> Result<String, NulError> {
let c_path = CString::new(path)?;
let c_language = CString::new(language)?;
unsafe {
Ok(GetMimeType(c_path.as_go_string(), c_language.as_go_string()).to_string())
}
pub fn get_mime_type<S: AsRef<str>>(path: S, language: S) -> Result<String, NulError> {
let c_path = CString::new(path.as_ref())?;
let c_language = CString::new(language.as_ref())?;
unsafe { Ok(GetMimeType(c_path.as_go_string(), c_language.as_go_string()).to_string()) }
}


/// `get_language_by_extension()` returns detected language.
///
/// If there are more than one possibles languages it returns the first language
/// by alphabetically order and the `safe` field of `Guess` will be set to false.
pub fn get_language_by_extension(filename: &str) -> Result<Guess, NulError> {
let c_filename = CString::new(filename)?;
unsafe { Ok(Guess::from(GetLanguageByExtension(c_filename.as_go_string()))) }
pub fn get_language_by_extension<S: AsRef<str>>(filename: S) -> Result<Guess, NulError> {
let c_filename = CString::new(filename.as_ref())?;
unsafe {
Ok(Guess::from(GetLanguageByExtension(
c_filename.as_go_string(),
)))
}
}

/// `get_language_by_filename()` returns detected language.
///
/// If there are more than one possibles languages it returns the first language
/// by alphabetically order and the `safe` field of `Guess` will be set to false.
pub fn get_language_by_filename(filename: &str) -> Result<Guess, NulError> {
let c_filename = CString::new(filename)?;
unsafe { Ok(Guess::from(GetLanguageByFilename(c_filename.as_go_string()))) }
pub fn get_language_by_filename<S: AsRef<str>>(filename: S) -> Result<Guess, NulError> {
let c_filename = CString::new(filename.as_ref())?;
unsafe {
Ok(Guess::from(GetLanguageByFilename(
c_filename.as_go_string(),
)))
}
}

/// `get_language_by_modeline()` returns detected language.
///
/// If there are more than one possibles languages it returns the first language
/// by alphabetically order and the `safe` field of `Guess` will be set to false.
pub fn get_language_by_modeline(content: &[u8]) -> Result<Guess, NulError> {
let c_content = CString::new(content)?;
pub fn get_language_by_modeline<B: AsRef<[u8]>>(content: B) -> Result<Guess, NulError> {
let c_content = CString::new(content.as_ref())?;
unsafe { Ok(Guess::from(GetLanguageByModeline(c_content.as_go_slice()))) }
}

/// `get_language_by_shebang()` returns detected language.
///
/// If there are more than one possibles languages it returns the first language
/// by alphabetically order and the `safe` field of `Guess` will be set to false.
pub fn get_language_by_shebang(content: &[u8]) -> Result<Guess, NulError> {
let c_content = CString::new(content)?;
pub fn get_language_by_shebang<B: AsRef<[u8]>>(content: B) -> Result<Guess, NulError> {
let c_content = CString::new(content.as_ref())?;
unsafe { Ok(Guess::from(GetLanguageByShebang(c_content.as_go_slice()))) }
}

/// `get_language_by_vim_modeline()` returns detected language.
///
/// If there are more than one possibles languages it returns the first language
/// by alphabetically order and the `safe` field of `Guess` will be set to false.
pub fn get_language_by_vim_modeline(content: &[u8]) -> Result<Guess, NulError> {
let c_content = CString::new(content)?;
unsafe { Ok(Guess::from(GetLanguageByVimModeline(c_content.as_go_slice()))) }
pub fn get_language_by_vim_modeline<B: AsRef<[u8]>>(content: B) -> Result<Guess, NulError> {
let c_content = CString::new(content.as_ref())?;
unsafe {
Ok(Guess::from(GetLanguageByVimModeline(
c_content.as_go_slice(),
)))
}
}

/// `get_language_by_emacs_modeline()` returns detected language.
///
/// If there are more than one possibles languages it returns the first language
/// by alphabetically order and the `safe` field of `Guess` will be set to false.
pub fn get_language_by_emacs_modeline(content: &[u8]) -> Result<Guess, NulError> {
let c_content = CString::new(content)?;
unsafe { Ok(Guess::from(GetLanguageByEmacsModeline(c_content.as_go_slice()))) }
pub fn get_language_by_emacs_modeline<B: AsRef<[u8]>>(content: B) -> Result<Guess, NulError> {
let c_content = CString::new(content.as_ref())?;
unsafe {
Ok(Guess::from(GetLanguageByEmacsModeline(
c_content.as_go_slice(),
)))
}
}

/// `is_binary()` detects if data is a binary value based
/// on this [code snippet](http://git.kernel.org/cgit/git/git.git/tree/xdiff-interface.c?id=HEAD#n198).
pub fn is_binary(data: &[u8]) -> Result<bool, NulError> {
let c_data = CString::new(data)?;
pub fn is_binary<B: AsRef<[u8]>>(data: B) -> Result<bool, NulError> {
let c_data = CString::new(data.as_ref())?;
unsafe { Ok(IsBinary(c_data.as_go_slice()) == 1) }
}

/// `is_configuration()` tells if filename is in one of the configuration languages.
pub fn is_configuration(path: &str) -> Result<bool, NulError> {
let c_path = CString::new(path)?;
pub fn is_configuration<S: AsRef<str>>(path: S) -> Result<bool, NulError> {
let c_path = CString::new(path.as_ref())?;
unsafe { Ok(IsConfiguration(c_path.as_go_string()) == 1) }
}

/// `is_documentation()` returns whether or not path is a documentation path.
pub fn is_documentation(path: &str) -> Result<bool, NulError> {
let c_path = CString::new(path)?;
pub fn is_documentation<S: AsRef<str>>(path: S) -> Result<bool, NulError> {
let c_path = CString::new(path.as_ref())?;
unsafe { Ok(IsDocumentation(c_path.as_go_string()) == 1) }
}

/// `is_dot_file()` returns whether or not path has dot as a prefix.
pub fn is_dot_file(path: &str) -> Result<bool, NulError> {
let c_path = CString::new(path)?;
pub fn is_dot_file<S: AsRef<str>>(path: S) -> Result<bool, NulError> {
let c_path = CString::new(path.as_ref())?;
unsafe { Ok(IsDotFile(c_path.as_go_string()) == 1) }
}

/// `is_image()` tells if a given file is an image (PNG, JPEG or GIF format).
pub fn is_image(path: &str) -> Result<bool, NulError> {
let c_path = CString::new(path)?;
pub fn is_image<S: AsRef<str>>(path: S) -> Result<bool, NulError> {
let c_path = CString::new(path.as_ref())?;
unsafe { Ok(IsImage(c_path.as_go_string()) == 1) }
}

/// `is_vendor()` returns whether or not path is a vendor path.
pub fn is_vendor(path: &str) -> Result<bool, NulError> {
let c_path = CString::new(path)?;
pub fn is_vendor<S: AsRef<str>>(path: S) -> Result<bool, NulError> {
let c_path = CString::new(path.as_ref())?;
unsafe { Ok(IsVendor(c_path.as_go_string()) == 1) }
}

/// `is_generated()` returns whether the file with the given path and content
/// is a generated file.
pub fn is_generated(path: &str, content: &[u8]) -> Result<bool, NulError> {
let c_path = CString::new(path)?;
let c_content = CString::new(content)?;
pub fn is_generated<S: AsRef<str>, B: AsRef<[u8]>>(path: S, content: B) -> Result<bool, NulError> {
let c_path = CString::new(path.as_ref())?;
let c_content = CString::new(content.as_ref())?;
unsafe { Ok(IsGenerated(c_path.as_go_string(), c_content.as_go_slice()) == 1) }
}

/// `get_color()` returns the HTML color code of a given language.
pub fn get_color(language: &str) -> Result<String, NulError> {
let c_language = CString::new(language)?;
pub fn get_color<S: AsRef<str>>(language: S) -> Result<String, NulError> {
let c_language = CString::new(language.as_ref())?;
unsafe { Ok(GetColor(c_language.as_go_string()).to_string()) }
}
Loading