@@ -12,11 +12,11 @@
Loading
12 12
    Base._return_type(f, maptoTuple(_unsafe_get_eltype, A, As...))
13 13
14 14
function Dates.DateTime(dt::DataValue{T}, format::AbstractString; locale::Dates.Locale=Dates.ENGLISH) where {T <: AbstractString}
15 -
    isna(dt) ? DataValue{DateTime}() : DataValue{DateTime}(DateTime(get(dt), format, locale=locale))
15 +
    isna(dt) ? DataValue{DateTime}() : DataValue{DateTime}(DateTime(unsafe_get(dt), format, locale=locale))
16 16
end
17 17
18 18
function Dates.Date(dt::DataValue{T}, format::AbstractString; locale::Dates.Locale=Dates.ENGLISH) where {T <: AbstractString}
19 -
    isna(dt) ? DataValue{Date}() : DataValue{Date}(Date(get(dt), format, locale=locale))
19 +
    isna(dt) ? DataValue{Date}() : DataValue{Date}(Date(unsafe_get(dt), format, locale=locale))
20 20
end
21 21
22 22
for f in (:(Base.abs), :(Base.abs2), :(Base.conj),:(Base.sign))
@@ -25,7 +25,7 @@
Loading
25 25
            if isna(a)
26 26
                DataValue{T}()
27 27
            else
28 -
                DataValue($f(get(a)))
28 +
                DataValue($f(unsafe_get(a)))
29 29
            end
30 30
        end
31 31
    end
@@ -42,7 +42,7 @@
Loading
42 42
            if isna(a)
43 43
                DataValue{Float64}()
44 44
            else
45 -
                DataValue{Float64}($f(get(a)))
45 +
                DataValue{Float64}($f(unsafe_get(a)))
46 46
            end
47 47
        end
48 48
    end

@@ -24,6 +24,14 @@
Loading
24 24
    return DataValueArray{T,N}(Array{T,N}(undef, d), fill(true, d))    
25 25
end
26 26
27 +
function DataValueArray{T, N}(::UndefInitializer, args...) where {T, N}
28 +
    return DataValueArray(Array{T, N}(undef, args...), fill(true, args...))
29 +
end
30 +
31 +
function DataValueArray{T}(::UndefInitializer, args...) where {T}
32 +
    return DataValueArray(Array{T}(undef, args...), fill(true, args...))
33 +
end
34 +
27 35
function DataValueArray(data::AbstractArray{T,N}) where {T<:DataValue,N}
28 36
    S = eltype(eltype(data))
29 37
    new_array = DataValueArray{S,N}(Array{S}(undef, size(data)), Array{Bool}(undef, size(data)))
@@ -67,6 +75,14 @@
Loading
67 75
    return DataValueArray{T,N}(convert(Array{T,N}, A), fill(false, size(A)))
68 76
end
69 77
78 +
function Base.convert(::Type{DataValueArray{T,N}}, A::AbstractArray{S,N}) where {S>:Any,T,N}
79 +
    new_array = DataValueArray{T,N}(Array{T}(undef, size(A)), Array{Bool}(undef, size(A)))
80 +
    for i in eachindex(A)
81 +
        new_array[i] = A[i]
82 +
    end
83 +
    return new_array
84 +
end
85 +
70 86
function Base.convert(::Type{DataValueArray{T}}, A::AbstractArray{S,N}) where {S,T,N}
71 87
    return convert(DataValueArray{T,N}, A)
72 88
end

@@ -14,14 +14,16 @@
Loading
14 14
`DataValue{T}` container. If the value is missing, then this method returns
15 15
`DataValue{T}()`.
16 16
"""
17 -
@inline function Base.getindex(X::DataValueArray{T,N}, I::Int...) where {T,N}
17 +
@inline function Base.getindex(X::DataValueArray{T,N}, i::Int) where {T,N}
18 +
    @boundscheck checkbounds(X, i)
18 19
    if isbitstype(T)
19 -
        ifelse(X.isna[I...], DataValue{T}(), DataValue{T}(X.values[I...]))
20 +
        @inbounds r = DataValue{T}(X.values[i], !X.isna[i])
21 +
        return r
20 22
    else
21 -
        if X.isna[I...]
22 -
            DataValue{T}()
23 +
        @inbounds if X.isna[i]
24 +
            return DataValue{T}()
23 25
        else
24 -
            DataValue{T}(X.values[I...])
26 +
            return DataValue{T}(X.values[i])
25 27
        end
26 28
    end
27 29
end

@@ -25,16 +25,19 @@
Loading
25 25
Base.convert(t::Type{DataValue{T}}, x::Any) where {T} = convert(t, convert(T, x))
26 26
27 27
function Base.convert(::Type{DataValue{T}}, x::DataValue) where {T}
28 -
    return isna(x) ? DataValue{T}() : DataValue{T}(convert(T, get(x)))
28 +
    return isna(x) ? DataValue{T}() : DataValue{T}(convert(T, unsafe_get(x)))
29 29
end
30 30
31 31
Base.convert(::Type{DataValue{T}}, x::T) where {T} = DataValue{T}(x)
32 32
Base.convert(::Type{DataValue}, x::T) where {T} = DataValue{T}(x)
33 33
34 +
Base.convert(::Type{DataValue{T}}, ::Missing) where {T} = DataValue{T}()
35 +
Base.convert(::Type{DataValue}, ::Missing) = DataValue{Union{}}()
36 +
34 37
Base.convert(::Type{DataValue{T}}, ::Nothing) where {T} = DataValue{T}()
35 38
Base.convert(::Type{DataValue}, ::Nothing) = DataValue{Union{}}()
36 39
37 -
Base.convert(::Type{Union{Missing, T}}, value::DataValues.DataValue{T}) where T = isna(value) ? missing : value[]
40 +
Base.convert(::Type{Union{Missing, T}}, value::DataValues.DataValue{T}) where T = get(value, missing)
38 41
Base.convert(::Type{Union{Missing, T}}, ::DataValues.DataValue{Union{}}) where T = missing
39 42
Base.convert(::Type{Missing}, ::DataValue{Union{}}) = missing
40 43
@@ -50,14 +53,14 @@
Loading
50 53
        if isna(x)
51 54
            print(io, "#NA")
52 55
        else
53 -
            show(io, x.value)
56 +
            show(io, unsafe_get(x))
54 57
        end
55 58
    else
56 59
        print(io, "DataValue{")
57 60
        show(IOContext(io, :compact => true), eltype(x))
58 61
        print(io, "}(")
59 62
        if !isna(x)
60 -
            show(IOContext(io, :compact => true), x.value)
63 +
            show(IOContext(io, :compact => true), unsafe_get(x))
61 64
        end
62 65
        print(io, ')')
63 66
    end
@@ -65,13 +68,13 @@
Loading
65 68
66 69
@inline function Base.get(x::DataValue{S}, y::T) where {S,T}
67 70
    if isbitstype(S)
68 -
        ifelse(isna(x), y, x.value)
71 +
        ifelse(isna(x), y, unsafe_get(x))
69 72
    else
70 -
        isna(x) ? y : x.value
73 +
        isna(x) ? y : unsafe_get(x)
71 74
    end
72 75
end
73 76
74 -
Base.get(x::DataValue) = isna(x) ? throw(DataValueException()) : x.value
77 +
Base.get(x::DataValue) = isna(x) ? throw(DataValueException()) : unsafe_get(x)
75 78
76 79
"""
77 80
    getindex(x::DataValue)
@@ -79,7 +82,7 @@
Loading
79 82
Attempt to access the value of `x`. Throw a `DataValueException` if the
80 83
value is not present. Usually, this is written as `x[]`.
81 84
"""
82 -
Base.getindex(x::DataValue) = isna(x) ? throw(DataValueException()) : x.value
85 +
Base.getindex(x::DataValue) = isna(x) ? throw(DataValueException()) : unsafe_get(x)
83 86
84 87
Base.get(x::DataValue{Union{}}) = throw(DataValueException())
85 88
Base.get(x::DataValue{Union{}}, y) = y
@@ -97,7 +100,7 @@
Loading
97 100
    if isna(x)
98 101
        return h + DataValuehash_seed
99 102
    else
100 -
        return hash(x.value, h + DataValuehash_seed)
103 +
        return hash(unsafe_get(x), h)
101 104
    end
102 105
end
103 106
@@ -121,6 +124,7 @@
Loading
121 124
==(a::DataValue{Union{}}, b::DataValue{Union{}}) = true
122 125
!=(a::DataValue{T},b::DataValue{Union{}}) where {T} = !isna(a)
123 126
!=(a::DataValue{Union{}},b::DataValue{T}) where {T} = !isna(b)
127 +
!=(a::DataValue{Union{}}, b::DataValue{Union{}}) = false
124 128
125 129
# Strings
126 130
@@ -130,18 +134,45 @@
Loading
130 134
            if isna(x)
131 135
                return DataValue{T}()
132 136
            else
133 -
                return DataValue($op(get(x)))
137 +
                return DataValue($op(unsafe_get(x)))
134 138
            end
135 139
        end
136 140
    end
137 141
end
138 142
143 +
function Base.rstrip(f, s::DataValue{T}) where {T <: AbstractString}
144 +
    return isna(s) ? DataValue{SubString{T}}() : DataValue(rstrip(f, unsafe_get(s)))
145 +
end
146 +
function Base.rstrip(s::DataValue{T}, chars::Base.Chars) where {T <: AbstractString}
147 +
    return isna(s) ? DataValue{SubString{T}}() : DataValue(rstrip(unsafe_get(s), chars))
148 +
end
149 +
function Base.rstrip(s::DataValue{T}) where {T <: AbstractString}
150 +
    return isna(s) ? DataValue{SubString{T}}() : DataValue(rstrip(unsafe_get(s)))
151 +
end
152 +
153 +
function Base.lstrip(f, s::DataValue{T}) where {T <: AbstractString}
154 +
    return isna(s) ? DataValue{SubString{T}}() : DataValue(lstrip(f, unsafe_get(s)))
155 +
end
156 +
function Base.lstrip(s::DataValue{T}, chars::Base.Chars) where {T <: AbstractString}
157 +
    return isna(s) ? DataValue{SubString{T}}() : DataValue(lstrip(unsafe_get(s), chars))
158 +
end
159 +
function Base.lstrip(s::DataValue{T}) where {T <: AbstractString}
160 +
    return isna(s) ? DataValue{SubString{T}}() : DataValue(lstrip(unsafe_get(s)))
161 +
end
162 +
163 +
function Base.strip(s::DataValue{T}, chars::Base.Chars) where {T <: AbstractString}
164 +
    return isna(s) ? DataValue{SubString{T}}() : DataValue(strip(unsafe_get(s), chars))
165 +
end
166 +
function Base.strip(s::DataValue{T}) where {T <: AbstractString}
167 +
    return isna(s) ? DataValue{SubString{T}}() : DataValue(strip(unsafe_get(s)))
168 +
end
169 +
139 170
import Base.getindex
140 171
function Base.getindex(s::DataValue{T},i) where {T <: AbstractString}
141 172
    if isna(s)
142 173
        return DataValue{T}()
143 174
    else
144 -
        return DataValue(get(s)[i])
175 +
        return DataValue(unsafe_get(s)[i])
145 176
    end
146 177
end
147 178
@@ -150,7 +181,7 @@
Loading
150 181
        # TODO Decide whether this makes sense?
151 182
        return 0
152 183
    else
153 -
        return lastindex(get(s))
184 +
        return lastindex(unsafe_get(s))
154 185
    end
155 186
end
156 187
@@ -159,7 +190,7 @@
Loading
159 190
    if isna(s)
160 191
        return DataValue{Int}()
161 192
    else
162 -
        return DataValue{Int}(length(get(s)))
193 +
        return DataValue{Int}(length(unsafe_get(s)))
163 194
    end
164 195
end
165 196
@@ -168,7 +199,7 @@
Loading
168 199
for op in (:+, :-, :!, :~)
169 200
    @eval begin
170 201
        import Base.$(op)
171 -
        $op(x::DataValue{T}) where {T <: Number} = isna(x) ? DataValue{T}() : DataValue($op(get(x)))
202 +
        $op(x::DataValue{T}) where {T <: Number} = isna(x) ? DataValue{T}() : DataValue($op(unsafe_get(x)))
172 203
    end
173 204
end
174 205
@@ -176,43 +207,43 @@
Loading
176 207
for op in (:+, :-, :*, :/, :%, :&, :|, :^, :<<, :>>, :min, :max)
177 208
    @eval begin
178 209
        import Base.$(op)
179 -
        $op(a::DataValue{T1},b::DataValue{T2}) where {T1 <: Number,T2 <: Number} = isna(a) || isna(b) ? DataValue{promote_type(T1,T2)}() : DataValue{promote_type(T1,T2)}($op(get(a), get(b)))
180 -
        $op(x::DataValue{T1},y::T2) where {T1 <: Number,T2 <: Number} = isna(x) ? DataValue{promote_type(T1,T2)}() : DataValue{promote_type(T1,T2)}($op(get(x), y))
181 -
        $op(x::T1,y::DataValue{T2}) where {T1 <: Number,T2 <: Number} = isna(y) ? DataValue{promote_type(T1,T2)}() : DataValue{promote_type(T1,T2)}($op(x, get(y)))
210 +
        $op(a::DataValue{T1},b::DataValue{T2}) where {T1 <: Number,T2 <: Number} = isna(a) || isna(b) ? DataValue{promote_type(T1,T2)}() : DataValue{promote_type(T1,T2)}($op(unsafe_get(a), unsafe_get(b)))
211 +
        $op(x::DataValue{T1},y::T2) where {T1 <: Number,T2 <: Number} = isna(x) ? DataValue{promote_type(T1,T2)}() : DataValue{promote_type(T1,T2)}($op(unsafe_get(x), y))
212 +
        $op(x::T1,y::DataValue{T2}) where {T1 <: Number,T2 <: Number} = isna(y) ? DataValue{promote_type(T1,T2)}() : DataValue{promote_type(T1,T2)}($op(x, unsafe_get(y)))
182 213
    end
183 214
end
184 215
185 -
^(x::DataValue{T},p::Integer) where {T <: Number} = isna(x) ? DataValue{T}() : DataValue(get(x)^p)
186 -
(/)(x::DataValue{T}, y::DataValue{S}) where {T<:Integer,S<:Integer} = (isna(x) | isna(y)) ? DataValue{Float64}() : DataValue{Float64}(float(get(x)) / float(get(y)))
187 -
(/)(x::DataValue{T}, y::S) where {T<:Integer,S<:Integer} = isna(x) ? DataValue{Float64}() : DataValue{Float64}(float(get(x)) / float(y))
188 -
(/)(x::T, y::DataValue{S}) where {T<:Integer,S<:Integer} = isna(y) ? DataValue{Float64}() : DataValue{Float64}(float(x) / float(get(y)))
216 +
^(x::DataValue{T},p::Integer) where {T <: Number} = isna(x) ? DataValue{T}() : DataValue(unsafe_get(x)^p)
217 +
(/)(x::DataValue{T}, y::DataValue{S}) where {T<:Integer,S<:Integer} = (isna(x) | isna(y)) ? DataValue{Float64}() : DataValue{Float64}(float(unsafe_get(x)) / float(unsafe_get(y)))
218 +
(/)(x::DataValue{T}, y::S) where {T<:Integer,S<:Integer} = isna(x) ? DataValue{Float64}() : DataValue{Float64}(float(unsafe_get(x)) / float(y))
219 +
(/)(x::T, y::DataValue{S}) where {T<:Integer,S<:Integer} = isna(y) ? DataValue{Float64}() : DataValue{Float64}(float(x) / float(unsafe_get(y)))
189 220
190 -
==(a::DataValue{T1},b::DataValue{T2}) where {T1,T2} = isna(a) && isna(b) ? true : !isna(a) && !isna(b) ? get(a)==get(b) : false
191 -
==(a::DataValue{T1},b::T2) where {T1,T2} = isna(a) ? false : get(a)==b
192 -
==(a::T1,b::DataValue{T2}) where {T1,T2} = isna(b) ? false : a==get(b)
221 +
==(a::DataValue{T1},b::DataValue{T2}) where {T1,T2} = isna(a) && isna(b) ? true : !isna(a) && !isna(b) ? unsafe_get(a)==unsafe_get(b) : false
222 +
==(a::DataValue{T1},b::T2) where {T1,T2} = isna(a) ? false : unsafe_get(a)==b
223 +
==(a::T1,b::DataValue{T2}) where {T1,T2} = isna(b) ? false : a==unsafe_get(b)
193 224
194 -
!=(a::DataValue{T1},b::DataValue{T2}) where {T1,T2} = isna(a) && isna(b) ? false : !isna(a) && !isna(b) ? get(a)!=get(b) : true
195 -
!=(a::DataValue{T1},b::T2) where {T1,T2} = isna(a) ? true : get(a)!=b
196 -
!=(a::T1,b::DataValue{T2}) where {T1,T2} = isna(b) ? true : a!=get(b)
225 +
!=(a::DataValue{T1},b::DataValue{T2}) where {T1,T2} = isna(a) && isna(b) ? false : !isna(a) && !isna(b) ? unsafe_get(a)!=unsafe_get(b) : true
226 +
!=(a::DataValue{T1},b::T2) where {T1,T2} = isna(a) ? true : unsafe_get(a)!=b
227 +
!=(a::T1,b::DataValue{T2}) where {T1,T2} = isna(b) ? true : a!=unsafe_get(b)
197 228
198 229
for op in (:<,:>,:<=,:>=)
199 230
    @eval begin
200 231
        import Base.$(op)
201 -
        $op(a::DataValue{T},b::DataValue{T}) where {T <: Number} = isna(a) || isna(b) ? false : $op(get(a), get(b))
202 -
        $op(x::DataValue{T1},y::T2) where {T1 <: Number,T2 <: Number} = isna(x) ? false : $op(get(x), y)
203 -
        $op(x::T1,y::DataValue{T2}) where {T1 <: Number,T2 <: Number} = isna(y) ? false : $op(x, get(y))
232 +
        $op(a::DataValue{T},b::DataValue{T}) where {T <: Number} = isna(a) || isna(b) ? false : $op(unsafe_get(a), unsafe_get(b))
233 +
        $op(x::DataValue{T1},y::T2) where {T1 <: Number,T2 <: Number} = isna(x) ? false : $op(unsafe_get(x), y)
234 +
        $op(x::T1,y::DataValue{T2}) where {T1 <: Number,T2 <: Number} = isna(y) ? false : $op(x, unsafe_get(y))
204 235
    end
205 236
end
206 237
207 238
# C# spec 7.11.4
208 239
function (&)(x::DataValue{Bool},y::DataValue{Bool})
209 240
    if isna(x)
210 -
        if isna(y) || get(y)==true
241 +
        if isna(y) || unsafe_get(y)==true
211 242
            return DataValue{Bool}()
212 243
        else
213 244
            return DataValue(false)
214 245
        end
215 -
    elseif get(x)==true
246 +
    elseif unsafe_get(x)==true
216 247
        return y
217 248
    else
218 249
        return DataValue(false)
@@ -224,12 +255,12 @@
Loading
224 255
225 256
function (|)(x::DataValue{Bool},y::DataValue{Bool})
226 257
    if isna(x)
227 -
        if isna(y) || !get(y)
258 +
        if isna(y) || !unsafe_get(y)
228 259
            return DataValue{Bool}()
229 260
        else
230 261
            return DataValue(true)
231 262
        end
232 -
    elseif get(x)
263 +
    elseif unsafe_get(x)
233 264
        return DataValue(true)
234 265
    else
235 266
        return y
@@ -246,13 +277,13 @@
Loading
246 277
    elseif isna(y)
247 278
        return true
248 279
    else
249 -
        return isless(x.value, y.value)
280 +
        return isless(unsafe_get(x), unsafe_get(y))
250 281
    end
251 282
end
252 283
253 -
isless(x::S, y::DataValue{T}) where {S,T} = isna(y) ? true : isless(x, get(y))
284 +
isless(x::S, y::DataValue{T}) where {S,T} = isna(y) ? true : isless(x, unsafe_get(y))
254 285
255 -
isless(x::DataValue{S}, y::T) where {S,T} = isna(x) ? false : isless(get(x), y)
286 +
isless(x::DataValue{S}, y::T) where {S,T} = isna(x) ? false : isless(unsafe_get(x), y)
256 287
257 288
isless(x::DataValue{Union{}}, y::DataValue{Union{}}) = false
258 289
@@ -262,14 +293,21 @@
Loading
262 293
263 294
# TODO Is that the definition we want?
264 295
function Base.isnan(x::DataValue{T}) where {T<:AbstractFloat}
265 -
    return !isna(x) && isnan(x[])
296 +
    return !isna(x) && isnan(unsafe_get(x))
266 297
end
267 298
268 299
# TODO Is that the definition we want?
269 300
function Base.isfinite(x::DataValue{T}) where {T<:AbstractFloat}
270 -
    return !isna(x) && isfinite(x[])
301 +
    return !isna(x) && isfinite(unsafe_get(x))
271 302
end
272 303
273 304
function Base.float(x::DataValue{T}) where T
274 -
    return isna(x) ? DataValue{Float64}() : DataValue{Float64}(float(get(x)))
305 +
    return isna(x) ? DataValue{Float64}() : DataValue{Float64}(float(unsafe_get(x)))
275 306
end
307 +
308 +
# DataValueInterfaces definitions
309 +
using DataValueInterfaces
310 +
DataValueInterfaces.nondatavaluetype(::Type{DataValue{T}}) where {T} = Union{T, Missing}
311 +
DataValueInterfaces.datavaluetype(::Type{T}) where {T <: DataValue} = T
312 +
DataValueInterfaces.datavaluetype(::Type{Union{T, Missing}}) where {T} = DataValue{T}
313 +
DataValueInterfaces.datavaluetype(::Type{Missing}) = DataValue{Union{}}

@@ -1,4 +1,3 @@
Loading
1 -
__precompile__()
2 1
module DataValues
3 2
4 3
using Dates
Files Coverage
src 74.90%
Project Totals (13 files) 74.90%
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading