{-# LANGUAGE OverloadedStrings #-}
module OpenTelemetry.Metric.InstrumentName (
validateInstrumentName,
validateInstrumentUnit,
) where
import Data.Char (isAscii)
import Data.Text (Text)
import qualified Data.Text as T
validateInstrumentName :: Text -> Maybe Text
validateInstrumentName :: Text -> Maybe Text
validateInstrumentName Text
t
| Text -> Bool
T.null Text
t = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"instrument name must not be empty"
| Text -> Int
T.length Text
t Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
255 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"instrument name exceeds 255 characters"
| Bool
otherwise =
let c0 :: Char
c0 = HasCallStack => Text -> Int -> Char
Text -> Int -> Char
T.index Text
t Int
0
in if Bool -> Bool
not (Char -> Bool
isAsciiAlpha Char
c0)
then Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"instrument name must start with an ASCII letter"
else Int -> Maybe Text
go Int
1
where
go :: Int -> Maybe Text
go :: Int -> Maybe Text
go Int
i
| Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Text -> Int
T.length Text
t = Maybe Text
forall a. Maybe a
Nothing
| Bool
otherwise =
let c :: Char
c = HasCallStack => Text -> Int -> Char
Text -> Int -> Char
T.index Text
t Int
i
in if Char -> Bool
isValidChar Char
c
then Int -> Maybe Text
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
else Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"instrument name contains invalid characters"
isAsciiAlpha :: Char -> Bool
isAsciiAlpha Char
c =
Char -> Bool
isAscii Char
c
Bool -> Bool -> Bool
&& ((Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'A' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'Z') Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'a' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'z'))
isAsciiDigit :: Char -> Bool
isAsciiDigit Char
c = Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'0' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9'
isValidChar :: Char -> Bool
isValidChar Char
c =
Char -> Bool
isAscii Char
c
Bool -> Bool -> Bool
&& ( Char -> Bool
isAsciiAlpha Char
c
Bool -> Bool -> Bool
|| Char -> Bool
isAsciiDigit Char
c
Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'_'
Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.'
Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-'
Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'/'
)
validateInstrumentUnit :: Text -> Maybe Text
validateInstrumentUnit :: Text -> Maybe Text
validateInstrumentUnit Text
u
| Text -> Bool
T.null Text
u = Maybe Text
forall a. Maybe a
Nothing
| Text -> Int
T.length Text
u Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
63 = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"instrument unit exceeds 63 characters"
| Bool
otherwise =
let step :: Int -> Maybe a
step Int
i
| Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Text -> Int
T.length Text
u = Maybe a
forall a. Maybe a
Nothing
| Bool
otherwise =
let c :: Char
c = HasCallStack => Text -> Int -> Char
Text -> Int -> Char
T.index Text
u Int
i
in if Char -> Bool
isAscii Char
c then Int -> Maybe a
step (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) else a -> Maybe a
forall a. a -> Maybe a
Just a
"instrument unit must be ASCII"
in Int -> Maybe Text
forall {a}. IsString a => Int -> Maybe a
step Int
0