1 module Databrary.Store.Filename
    2   ( makeFilename
    3   ) where
    4 
    5 import qualified Data.ByteString as BS
    6 import qualified Data.ByteString.Builder as BSB
    7 import qualified Data.ByteString.Lazy as BSL
    8 import Data.Char (isSpace)
    9 import Data.List (intersperse)
   10 import Data.Monoid ((<>))
   11 import qualified Data.Text as T
   12 
   13 truncateFilename :: T.Text -> Int
   14 truncateFilename s
   15   | len <= maxlen = len
   16   | otherwise = fr maxlen where
   17   len = T.length s
   18   fr n
   19     | n < maxlen `div` 2 = maxlen
   20     | isSpace (T.index s n) = n
   21     | otherwise = fr $ pred n
   22   maxlen = 32
   23 
   24 buildFilename :: T.Text -> BSB.Builder
   25 buildFilename t = fc (T.unpack t) len True where
   26   len = truncateFilename t
   27   fc [] _ _ = mempty
   28   fc _ 0 _ = mempty
   29   fc (c:s) n p
   30     | c < ',' || c `elem` "/?\\" = if p then r True else BSB.char8 '_' <> r True
   31     | otherwise = BSB.charUtf8 c <> r False
   32     where r = fc s (pred n)
   33 
   34 makeFilename :: [T.Text] -> BS.ByteString
   35 makeFilename = BSL.toStrict . BSB.toLazyByteString . mconcat . intersperse (BSB.char8 '-') . map buildFilename