diff --git a/src/FilePathsBase.jl b/src/FilePathsBase.jl index 8fed5c8..75ba834 100644 --- a/src/FilePathsBase.jl +++ b/src/FilePathsBase.jl @@ -99,10 +99,11 @@ function Base.show(io::IO, path::AbstractPath) get(io, :compact, false) ? print(io, path) : print(io, "p\"$(String(path))\"") end +Base.parse(::Type{<:AbstractPath}, x::AbstractString) = Path(x) Base.convert(::Type{AbstractPath}, x::AbstractString) = Path(x) Base.convert(::Type{String}, x::AbstractPath) = string(x) -Base.promote_rule(::Type{String}, ::Type{T}) where {T <: AbstractPath} = String -ispathtype(::Type{T}, x::AbstractString) where {T <: AbstractPath} = false +Base.promote_rule(::Type{String}, ::Type{<:AbstractPath}) = String +ispathtype(::Type{<:AbstractPath}, x::AbstractString) = false include("constants.jl") include("utils.jl") diff --git a/src/constants.jl b/src/constants.jl index 359cbe9..53a7d68 100644 --- a/src/constants.jl +++ b/src/constants.jl @@ -56,30 +56,30 @@ const S_IWOTH = 0o0002 # write by others const S_IXOTH = 0o0001 # execute by others const FILEMODE_TABLE = ( - ((S_IFLNK, "l"), - (S_IFREG, "-"), - (S_IFBLK, "b"), - (S_IFDIR, "d"), - (S_IFCHR, "c"), - (S_IFIFO, "p")), + ((S_IFLNK, 'l'), + (S_IFREG, '-'), + (S_IFBLK, 'b'), + (S_IFDIR, 'd'), + (S_IFCHR, 'c'), + (S_IFIFO, 'p')), - ((S_IRUSR, "r"),), - ((S_IWUSR, "w"),), - ((S_IXUSR|S_ISUID, "s"), - (S_ISUID, "S"), - (S_IXUSR, "x")), + ((S_IRUSR, 'r'),), + ((S_IWUSR, 'w'),), + ((S_IXUSR|S_ISUID, 's'), + (S_ISUID, 'S'), + (S_IXUSR, 'x')), - ((S_IRGRP, "r"),), - ((S_IWGRP, "w"),), - ((S_IXGRP|S_ISGID, "s"), - (S_ISGID, "S"), - (S_IXGRP, "x")), + ((S_IRGRP, 'r'),), + ((S_IWGRP, 'w'),), + ((S_IXGRP|S_ISGID, 's'), + (S_ISGID, 'S'), + (S_IXGRP, 'x')), - ((S_IROTH, "r"),), - ((S_IWOTH, "w"),), - ((S_IXOTH|S_ISVTX, "t"), - (S_ISVTX, "T"), - (S_IXOTH, "x")) + ((S_IROTH, 'r'),), + ((S_IWOTH, 'w'),), + ((S_IXOTH|S_ISVTX, 't'), + (S_ISVTX, 'T'), + (S_IXOTH, 'x')) ) -const DATA_SUFFIX = ["", "K", "M", "G", "T", "P", "E", "Z", "Y"] \ No newline at end of file +const DATA_SUFFIX = ["", "K", "M", "G", "T", "P", "E", "Z", "Y"] diff --git a/src/mode.jl b/src/mode.jl index edb256b..49508a9 100644 --- a/src/mode.jl +++ b/src/mode.jl @@ -43,8 +43,69 @@ function Mode(mode::UInt8, usr_grps::Symbol...) return Mode(user=user, group=group, other=other) end -Base.show(io::IO, mode::Mode) = print(io, string(mode)) -Base.string(mode::Mode) = String(mode) +Mode(s::AbstractString) = parse(Mode, s) + +function Base.parse(::Type{Mode}, x::AbstractString) + n = length(FILEMODE_TABLE) + + if length(x) != n + throw(ArgumentError( + "Expected a mode permission string with $n characters (e.g., '-rwxrwxrwx')" + )) + end + + m = zero(UInt64) + for i in 1:n + table = FILEMODE_TABLE[i] + found = false + c = x[i] + c == '-' && continue + + for (bit, char) in table + if c == char + m = m | bit + found = true + break + end + end + if !found + options = last.(table) + throw(ArgumentError( + "Unknown character '$c' at position $i, expected one of $options." + )) + end + end + + return Mode(m) +end + +"""Convert a file's mode to a string of the form '-rwxrwxrwx'.""" +function Base.String(mode::Mode) + n = length(FILEMODE_TABLE) + perm = Vector{Char}(undef, n) + + for i in 1:n + table = FILEMODE_TABLE[i] + found = false + for (bit, char) in table + if mode.m & bit == bit + perm[i] = char + found = true + break + end + end + if !found + perm[i] = '-' + end + end + + return String(perm) +end + +Base.print(io::IO, mode::Mode) = print(io, String(mode)) +function Base.show(io::IO, mode::Mode) + get(io, :compact, false) ? print(io, mode) : print(io, "Mode(\"$(String(mode))\")") +end Base.:-(a::Mode, b::Mode) = Mode(a.m & ~b.m) Base.:+(a::Mode, b::Mode) = Mode(a.m | b.m) @@ -119,27 +180,6 @@ Base.ischardev(mode::Mode) = _meta(mode.m) == S_IFCHR """Return True if mode is from a block special device file.""" Base.isblockdev(mode::Mode) = _meta(mode.m) == S_IFBLK - -"""Convert a file's mode to a string of the form '-rwxrwxrwx'.""" -function Base.String(mode::Mode) - perm = [] - for table in FILEMODE_TABLE - found = false - for (bit, char) in table - if mode.m & bit == bit - push!(perm, char) - found = true - break - end - end - if !found - push!(perm, '-') - end - end - - return join(perm) -end - """ Return the portion of the file's mode that can be set by os.chmod().