Skip to content

[cxx-interop] Add conversions between std::chrono::duration and Swift.Duration #72012

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 1, 2024
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
17 changes: 17 additions & 0 deletions stdlib/public/Cxx/cxxshim/libcxxstdlibshim.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <chrono>
#include <functional>
#include <string>

Expand All @@ -9,3 +10,19 @@ typedef std::hash<std::u16string> __swift_interopHashOfU16String;

/// Used for std::u32string conformance to Swift.Hashable
typedef std::hash<std::u32string> __swift_interopHashOfU32String;

inline std::chrono::seconds __swift_interopMakeChronoSeconds(int64_t seconds) {
return std::chrono::seconds(seconds);
}

inline std::chrono::milliseconds __swift_interopMakeChronoMilliseconds(int64_t milliseconds) {
return std::chrono::milliseconds(milliseconds);
}

inline std::chrono::microseconds __swift_interopMakeChronoMicroseconds(int64_t microseconds) {
return std::chrono::microseconds(microseconds);
}

inline std::chrono::nanoseconds __swift_interopMakeChronoNanoseconds(int64_t nanoseconds) {
return std::chrono::nanoseconds(nanoseconds);
}
1 change: 1 addition & 0 deletions stdlib/public/Cxx/std/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ endif()
# as it's not ABI stable.
add_swift_target_library(swiftCxxStdlib STATIC NO_LINK_NAME IS_STDLIB IS_SWIFT_ONLY IS_FRAGILE
std.swift
Chrono.swift
String.swift

SWIFT_MODULE_DEPENDS Cxx
Expand Down
70 changes: 70 additions & 0 deletions stdlib/public/Cxx/std/Chrono.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import CxxStdlibShim

extension std.chrono.seconds {
@available(SwiftStdlib 5.7, *)
public init(_ duration: Duration) {
let (seconds, _) = duration.components
self = __swift_interopMakeChronoSeconds(seconds)
}
}

extension std.chrono.milliseconds {
@available(SwiftStdlib 5.7, *)
public init(_ duration: Duration) {
let (seconds, attoseconds) = duration.components
self = __swift_interopMakeChronoMilliseconds(
seconds * 1_000 +
attoseconds / 1_000_000_000_000_000)
}
}

extension std.chrono.microseconds {
@available(SwiftStdlib 5.7, *)
public init(_ duration: Duration) {
let (seconds, attoseconds) = duration.components
self = __swift_interopMakeChronoMicroseconds(
seconds * 1_000_000 +
attoseconds / 1_000_000_000_000)
}
}

extension std.chrono.nanoseconds {
@available(SwiftStdlib 5.7, *)
public init(_ duration: Duration) {
let (seconds, attoseconds) = duration.components
self = __swift_interopMakeChronoNanoseconds(
seconds * 1_000_000_000 +
attoseconds / 1_000_000_000)
}
}

@available(SwiftStdlib 5.7, *)
extension Duration {
public init(_ seconds: std.chrono.seconds) {
self = Duration.seconds(seconds.count())
}

public init(_ milliseconds: std.chrono.milliseconds) {
self = Duration.milliseconds(milliseconds.count())
}

public init(_ microseconds: std.chrono.microseconds) {
self = Duration.microseconds(microseconds.count())
}

public init(_ nanoseconds: std.chrono.nanoseconds) {
self = Duration.nanoseconds(nanoseconds.count())
}
}
117 changes: 117 additions & 0 deletions test/Interop/Cxx/stdlib/use-std-chrono.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// RUN: %target-run-simple-swift(-I %S/Inputs -cxx-interoperability-mode=swift-6)
// RUN: %target-run-simple-swift(-I %S/Inputs -cxx-interoperability-mode=upcoming-swift)

// REQUIRES: executable_test

import StdlibUnittest
import CxxStdlib

var StdUniquePtrTestSuite = TestSuite("StdChrono")

if #available(SwiftStdlib 5.7, *) {
StdUniquePtrTestSuite.test("std::chrono::seconds <=> Duration") {
let d1 = Duration.seconds(123)
let c1 = std.chrono.seconds(d1)
expectEqual(123, c1.count())
expectEqual(d1, Duration(c1))

let d2 = Duration.milliseconds(1)
let c2 = std.chrono.seconds(d2)
expectEqual(0, c2.count())

let d3 = Duration.milliseconds(5000)
let c3 = std.chrono.seconds(d3)
expectEqual(5, c3.count())
expectEqual(d3, Duration(c3))

let d4 = Duration.seconds(-123)
let c4 = std.chrono.seconds(d4)
expectEqual(-123, c4.count())
expectEqual(d4, Duration(c4))

let d5 = Duration.milliseconds(-5000)
let c5 = std.chrono.seconds(d5)
expectEqual(-5, c5.count())
expectEqual(d5, Duration(c5))
}

StdUniquePtrTestSuite.test("std::chrono::milliseconds <=> Duration") {
let d1 = Duration.milliseconds(321)
let c1 = std.chrono.milliseconds(d1)
expectEqual(321, c1.count())
expectEqual(d1, Duration(c1))

let d2 = Duration.microseconds(1)
let c2 = std.chrono.milliseconds(d2)
expectEqual(0, c2.count())

let d3 = Duration.microseconds(2000)
let c3 = std.chrono.milliseconds(d3)
expectEqual(2, c3.count())
expectEqual(d3, Duration(c3))

let d4 = Duration.seconds(25)
let c4 = std.chrono.milliseconds(d4)
expectEqual(25000, c4.count())
expectEqual(d4, Duration(c4))

let d5 = Duration.microseconds(-5000)
let c5 = std.chrono.milliseconds(d5)
expectEqual(-5, c5.count())
expectEqual(d5, Duration(c5))
}

StdUniquePtrTestSuite.test("std::chrono::microseconds from Duration") {
let d1 = Duration.microseconds(456)
let c1 = std.chrono.microseconds(d1)
expectEqual(456, c1.count())
expectEqual(d1, Duration(c1))

let d2 = Duration.nanoseconds(1)
let c2 = std.chrono.milliseconds(d2)
expectEqual(0, c2.count())

let d3 = Duration.seconds(5)
let c3 = std.chrono.microseconds(d3)
expectEqual(5000000, c3.count())
expectEqual(d3, Duration(c3))

let d4 = Duration.milliseconds(5)
let c4 = std.chrono.microseconds(d4)
expectEqual(5000, c4.count())
expectEqual(d4, Duration(c4))

let d5 = Duration.microseconds(-654)
let c5 = std.chrono.microseconds(d5)
expectEqual(-654, c5.count())
expectEqual(d5, Duration(c5))
}

StdUniquePtrTestSuite.test("std::chrono::nanoseconds from Duration") {
let d1 = Duration.nanoseconds(789)
let c1 = std.chrono.nanoseconds(d1)
expectEqual(789, c1.count())
expectEqual(d1, Duration(c1))

let d2 = Duration.nanoseconds(1) / 1000
let c2 = std.chrono.nanoseconds(d2)
expectEqual(0, c2.count())

let d3 = Duration.seconds(5)
let c3 = std.chrono.nanoseconds(d3)
expectEqual(5000000000, c3.count())
expectEqual(d3, Duration(c3))

let d4 = Duration.milliseconds(2)
let c4 = std.chrono.nanoseconds(d4)
expectEqual(2000000, c4.count())
expectEqual(d4, Duration(c4))

let d5 = Duration.nanoseconds(-654)
let c5 = std.chrono.nanoseconds(d5)
expectEqual(-654, c5.count())
expectEqual(d5, Duration(c5))
}
}

runAllTests()