Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion .github/workflows/mhs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
matrix:
# windows doesn't quite work yet
os: [ubuntu-latest, macOS-15-intel, macOS-latest]
mhs: [0.15.0.0]
mhs: [0.16.0.0]

steps:

Expand Down
2 changes: 2 additions & 0 deletions System/OsString.hs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ module System.OsString

-- * Word construction
, unsafeFromChar
, fromWord

-- * Word deconstruction
, toChar
Expand Down Expand Up @@ -135,6 +136,7 @@ where

import System.OsString.Internal
( unsafeFromChar
, fromWord
, toChar
, encodeUtf
, unsafeEncodeUtf
Expand Down
34 changes: 34 additions & 0 deletions System/OsString/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ module System.OsString.MODULE_NAME

-- * Word construction
, unsafeFromChar
, fromWord

-- * Word deconstruction
, toChar
Expand Down Expand Up @@ -210,6 +211,11 @@ import Data.Bifunctor ( bimap )
import qualified System.OsString.Data.ByteString.Short.Word16 as BS16
import qualified System.OsString.Data.ByteString.Short as BS8

#ifdef WINDOWS
import Data.Word (Word16)
#else
import Data.Word (Word8)
#endif


#ifdef WINDOWS_DOC
Expand Down Expand Up @@ -538,6 +544,9 @@ unpack = coerce BSP.unpack
-- Note that using this in conjunction with 'unsafeFromChar' to
-- convert from @[Char]@ to platform string is probably not what
-- you want, because it will truncate unicode code points.
--
-- Additionally, a platform word is a byte (or wide char on windows) in an encoded byte sequence,
-- so we're not operating on unicode code points or graphemes here.
pack :: [PLATFORM_WORD] -> PLATFORM_STRING
pack = coerce BSP.pack

Expand All @@ -547,13 +556,38 @@ singleton = coerce BSP.singleton
empty :: PLATFORM_STRING
empty = mempty

#ifdef WINDOWS
-- | Convert from 'Word16'.
--
-- @since 2.0.11
fromWord :: Word16 -> PLATFORM_WORD
fromWord = WindowsChar
#else
-- | Convert from 'Word8'.
--
-- @since 2.0.11
fromWord :: Word8 -> PLATFORM_WORD
fromWord = PosixChar
#endif

#ifdef WINDOWS
-- | Truncates to 2 octets.
--
-- Note that 'WindowsChar' is a "wide char" in a UCS-2 encoded byte sequence
-- and is not morally a unicode code point by any means, so
-- this conversion is rarely what you want.
--
-- Consider using 'fromWord' instead.
unsafeFromChar :: Char -> PLATFORM_WORD
unsafeFromChar = WindowsChar . fromIntegral . fromEnum
#else
-- | Truncates to 1 octet.
--
-- Note that 'PosixChar' is a byte in an encoded byte sequence
-- and is not morally a unicode code point by any means, so
-- this conversion is rarely what you want.
--
-- Consider using 'fromWord' instead.
unsafeFromChar :: Char -> PLATFORM_WORD
unsafeFromChar = PosixChar . fromIntegral . fromEnum
#endif
Expand Down
20 changes: 20 additions & 0 deletions System/OsString/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import qualified System.OsString.Posix as PF
import GHC.Stack (HasCallStack)
import Data.Coerce (coerce)
import Data.Type.Coercion (coerceWith)
import Data.Word (Word8)



Expand Down Expand Up @@ -242,6 +243,9 @@ unpack = coerce PF.unpack
-- Note that using this in conjunction with 'unsafeFromChar' to
-- convert from @[Char]@ to 'OsString' is probably not what
-- you want, because it will truncate unicode code points.
--
-- Additionally, 'OsChar' is a byte (or wide char on windows) in an encoded byte sequence,
-- so we're not operating on unicode code points or graphemes here.
pack :: [OsChar] -> OsString
pack = coerce PF.pack

Expand All @@ -253,9 +257,25 @@ singleton = coerce PF.singleton


-- | Truncates on unix to 1 and on Windows to 2 octets.
--
-- Note that 'OsChar' is a byte in an encoded byte sequence
-- and is not morally a unicode code point by any means, so
-- this conversion is rarely what you want.
--
-- Consider using 'fromWord' instead.
unsafeFromChar :: Char -> OsChar
unsafeFromChar = coerce PF.unsafeFromChar

-- | Convert from 'Word8'.
--
-- @since 2.0.11
fromWord :: Word8 -> OsChar
#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
fromWord = OsChar . WindowsChar . fromIntegral
#else
fromWord = OsChar . PosixChar
#endif

-- | Converts back to a unicode codepoint (total).
toChar :: OsChar -> Char
toChar = case coercionToPlatformTypes of
Expand Down
17 changes: 14 additions & 3 deletions System/OsString/Internal/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,22 @@ type PlatformString = WindowsString
type PlatformString = PosixString
#endif

-- | This represents a "wide char" on windows.
--
-- A better name would maybe have been @WindowsWord@, since
-- this is just @Word16@ in a UCS-2 sequence.
newtype WindowsChar = WindowsChar { getWindowsChar :: Word16 }
deriving (Eq, Ord, Typeable, Generic, NFData)
deriving (Eq, Ord, Typeable, Generic, NFData, Lift)

instance Show WindowsChar where
show (WindowsChar wc) = show wc

-- | This represents a byte.
--
-- A better name would maybe have been @PosixWord@, since
-- it is just @Word8@ in an encoded byte sequence.
newtype PosixChar = PosixChar { getPosixChar :: Word8 }
deriving (Eq, Ord, Typeable, Generic, NFData)
deriving (Eq, Ord, Typeable, Generic, NFData, Lift)

instance Show PosixChar where
show (PosixChar pc) = show pc
Expand Down Expand Up @@ -205,8 +213,11 @@ instance Semigroup OsString where
--
-- On Windows, this is restricted to two-octet codepoints 'Word16',
-- on POSIX one-octet ('Word8').
--
-- This should maybe have been worded @OsWord@, since it is not
-- a unicode code point by any means. It represents a byte in a
newtype OsChar = OsChar { getOsChar :: PlatformChar }
deriving (Typeable, Generic, NFData)
deriving (Typeable, Generic, NFData, Lift)

instance Show OsChar where
show (OsChar pc) = show pc
Expand Down
5 changes: 5 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog for [`os-string` package](http://hackage.haskell.org/package/os-string)

## 2.0.11 *Jun 2026*

* Add Lift instance to `OsChar`, `PosixChar` and `WindowsChar`
* Add `fromWord`

## 2.0.10 *Jan 2026*

* fix build on GHC 9.14 wrt [#40](https://github.com/haskell/os-string/issues/40)
Expand Down
15 changes: 6 additions & 9 deletions os-string.cabal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cabal-version: 2.2
name: os-string
version: 2.0.10
version: 2.0.11

-- NOTE: Don't forget to update ./changelog.md
license: BSD-3-Clause
Expand All @@ -16,14 +16,11 @@ category: System
build-type: Simple
synopsis: Library for manipulating Operating system strings.
tested-with:
GHC ==8.6.5
|| ==8.8.4
|| ==8.10.7
|| ==9.0.2
|| ==9.2.8
|| ==9.4.8
|| ==9.6.3
|| ==9.8.1
GHC ==9.6.7
|| ==9.8.4
|| ==9.10.3
|| ==9.12.4
|| ==9.14.1

description:
This package provides functionality for manipulating @OsString@ values, and is shipped with <https://www.haskell.org/ghc/ GHC>.
Expand Down
Loading