{"id":24564955,"url":"https://github.com/helloitshessam/diffable","last_synced_at":"2025-04-19T20:57:14.481Z","repository":{"id":263844975,"uuid":"891567835","full_name":"helloItsHEssam/Diffable","owner":"helloItsHEssam","description":"The `@Diffable` macro provides an efficient way to calculate differences between two instances of a type.","archived":false,"fork":false,"pushed_at":"2024-11-21T07:06:07.000Z","size":18,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-12-23T11:03:03.850Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/helloItsHEssam.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-20T15:06:26.000Z","updated_at":"2024-11-30T13:14:21.000Z","dependencies_parsed_at":"2024-11-20T16:24:03.678Z","dependency_job_id":"4e53a255-1974-4559-9b0f-ba929ab7eba7","html_url":"https://github.com/helloItsHEssam/Diffable","commit_stats":null,"previous_names":["helloitshessam/diffable"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helloItsHEssam%2FDiffable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helloItsHEssam%2FDiffable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helloItsHEssam%2FDiffable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helloItsHEssam%2FDiffable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/helloItsHEssam","download_url":"https://codeload.github.com/helloItsHEssam/Diffable/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235272955,"owners_count":18963635,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-23T11:30:39.044Z","updated_at":"2025-01-23T11:30:40.007Z","avatar_url":"https://github.com/helloItsHEssam.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Diffable Macro  \n\n## Overview  \n\nThe `@Diffable` macro provides an efficient way to calculate differences between two instances of a type by automatically generating code to compare properties. It ensures that you only focus on the high-level design of your types while leveraging the macro for advanced functionality.  \n\nTo use the `@Diffable` macro, the target type must:  \n1. Be a `class`, `struct`, or `enum`.  \n2. Conform to the `Equatable` protocol.  \n\nThe macro will generate an optimized implementation of difference computation for all `Equatable` properties in your type.  \n\nWhen applied, the macro generates a computeDifference method that calculates the difference between two Config instances, returning a strongly-typed result indicating the changed properties.\n\n## How to using  \n\n```swift\n@Diffable\npublic struct Config: Equatable {\n    public var name: String\n    public var id: UUID\n}\n\n// expandedSource\npublic struct Config: Equatable {\n    public var name: String\n    public var id: UUID\n\n    public struct Difference: OptionSet {\n        public let rawValue: Int        \n        public init(rawValue: Int) {\n            self.rawValue = rawValue\n        }\n        static let name = Difference(rawValue: 1 \u003c\u003c 0)\n        static let id = Difference(rawValue: 1 \u003c\u003c 1)\n    }\n\n    public func computeDifference(from other: Self) -\u003e Difference {\n        var difference: Difference = []\n        var currentCopy: Self? = self\n        var otherCopy: Self? = other\n\n        if currentCopy?.name != otherCopy?.name {\n            difference.insert(.name)\n        }\n        \n        if currentCopy?.id != otherCopy?.id {\n            difference.insert(.id)\n        }\n        \n        currentCopy = nil\n        otherCopy = nil\n        return difference\n    }\n}\n\n// usage\nlet configOne = Config(name: \"HEssam\", id: UUID())\nlet configTwo = Config(name: \"Alfred\", id: UUID())\n\nlet differences = configOne.computeDifference(from: configTwo)\n```\n\n## Sample Using Diffable\n\n```swift\n/// A custom UIView that displays a person's name and age.\n/// This view uses a diffable configuration to detect and apply changes to its properties efficiently.\nfinal class PersonView: UIView {\n    \n    // MARK: - UI Elements\n    \n    /// Label to display the person's name.\n    private let nameLabel: UILabel = {\n        let label = UILabel()\n        label.font = .preferredFont(forTextStyle: .headline)\n        return label\n    }()\n    \n    /// Label to display the person's age.\n    private let ageLabel: UILabel = {\n        let label = UILabel()\n        label.font = .preferredFont(forTextStyle: .subheadline)\n        return label\n    }()\n    \n    // MARK: - Properties\n    \n    /// The current configuration of the view.\n    private var configuration: Configuration\n    \n    // MARK: - Initializers\n    \n    /// Initializes the view with the given configuration.\n    ///\n    /// - Parameter configuration: The initial configuration of the view.\n    init(configuration: Configuration) {\n        self.configuration = configuration\n        super.init(frame: .zero)\n    }\n    \n    @available(*, unavailable, message: \"init(frame:) is not supported. Use init(configuration:) instead.\")\n    override init(frame: CGRect) {\n        fatalError(\"init(frame:) has not been implemented\")\n    }\n    \n    @available(*, unavailable, message: \"init(coder:) is not supported. Use init(configuration:) instead.\")\n    required init?(coder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n    \n    // MARK: - Configuration Update\n    \n    /// Updates the view's configuration and applies changes to the UI.\n    ///\n    /// - Parameter configuration: The new configuration to apply.\n    func updateConfiguration(to configuration: Configuration) {\n        // Compute the differences between the old and new configurations.\n        let differences = self.configuration.computeDifference(from: configuration)\n        \n        // Iterate through potential differences and update the UI for changed properties.\n        for i in 0 ..\u003c Int.bitWidth {\n            let bit = 1 \u003c\u003c i\n            let difference = Configuration.Difference(rawValue: bit)\n            \n            if differences.contains(difference) {\n                switch difference {\n                case .age:\n                    // Update the age label if the age has changed.\n                    self.ageLabel.text = \"\\(configuration.age)\"\n                    \n                case .name:\n                    // Update the name label if the name has changed.\n                    self.nameLabel.text = configuration.name\n                    \n                default:\n                    break\n                }\n            }\n        }\n        \n        // Update the stored configuration.\n        self.configuration = configuration\n    }\n    \n    // MARK: - Configuration Struct\n    \n    /// Represents the configuration of the `PersonView`.\n    /// This struct uses the `@Diffable` macro to enable efficient change detection.\n    @Diffable\n    struct Configuration: Equatable {\n        /// The person's name.\n        let name: String\n        /// The person's age.\n        let age: Int\n    }\n}\n```\n\n\n\n\n\n## Error Handling\n\nThe `DiffableMacroError` enum provides detailed error cases to help developers debug issues when applying the macro.\n\n### Error Cases\n\n#### shouldBeClassOrStructOrEnum:\n- The macro is applied to an unsupported type. Only class, struct, or enum types are supported.\n\n#### shouldConformToEquatableProtocol:\n- The type does not conform to Equatable, which is required for the macro to function.\n\n## Contributing\nWe warmly welcome contributions to the BuildableMacro project! Whether you're fixing bugs, improving the documentation, or adding new features, your help is appreciated. Here’s how you can contribute:\n\n1. **Fork the Repository**: Start by forking the repository to your own GitHub account.\n2. **Create a Branch**: Make your changes in a new branch.\n3. **Make Your Changes**: Whether it's a new feature or a bug fix, your contributions make a difference.\n4. **Write Tests**: Ensure your changes are working as expected.\n5. **Submit a Pull Request**: Once you're satisfied, submit a pull request for review.\n\nTo give clarity of what is expected of our members, we have adopted the code of conduct defined by the Contributor Covenant. This document is used across many open source communities. For more, see the [Code of Conduct](CODE_OF_CONDUCT.md).\n\n[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](code_of_conduct.md)\n\n## License\n\nPlease check [LICENSE](LICENSE) for details.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhelloitshessam%2Fdiffable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhelloitshessam%2Fdiffable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhelloitshessam%2Fdiffable/lists"}